aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--Makefile.in31
-rw-r--r--doc/emacs/ChangeLog4
-rw-r--r--doc/emacs/files.texi3
-rw-r--r--doc/lispintro/emacs-lisp-intro.texi2
-rw-r--r--doc/lispref/ChangeLog4
-rw-r--r--doc/lispref/display.texi8
-rw-r--r--doc/misc/ChangeLog4
-rw-r--r--doc/misc/Makefile.in2
-rw-r--r--doc/misc/eshell.texi6
-rw-r--r--doc/misc/gnus-faq.texi8
-rw-r--r--doc/misc/gnus.texi12
-rw-r--r--doc/misc/semantic.texi2
-rw-r--r--doc/misc/speedbar.texi2
-rw-r--r--doc/misc/tramp.texi6
-rw-r--r--etc/MORE.STUFF3
-rw-r--r--etc/NEWS21
-rw-r--r--lisp/ChangeLog46
-rw-r--r--lisp/calc/calc-graph.el2
-rw-r--r--lisp/cmuscheme.el2
-rw-r--r--lisp/files.el18
-rw-r--r--lisp/info.el33
-rw-r--r--lisp/informat.el20
-rw-r--r--lisp/net/tramp-sh.el2
-rw-r--r--lisp/net/tramp.el20
-rw-r--r--lisp/progmodes/python.el65
-rw-r--r--src/ChangeLog4
-rw-r--r--src/sheap.c2
-rw-r--r--test/ChangeLog4
-rw-r--r--test/automated/python-tests.el1947
30 files changed, 2186 insertions, 109 deletions
diff --git a/ChangeLog b/ChangeLog
index e59e0646cb7..2720997a6c8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
12013-02-21 Paul Eggert <eggert@cs.ucla.edu>
2
3 Parallelize documentation builds.
4 This speeds up building of documentation on multiprocessor
5 platforms, and is motivated by Texinfo 5.0, which is much slower.
6 Add a toplevel rule 'make docs' to make all the documentation.
7 * .bzrignore: Add .dvi, .html, .ps.
8 * Makefile.in (DVIS, HTMLS, INFOS, PSS, DOCS): New macros.
9 ($(DOCS), docs, vi, html, pdf, ps): New rules.
10 (info-real): Depend on $(INFOS) rather than doing it sequentially.
11 (dvi): Depend on $(DVIS) rather than doing it sequentially.
12
12013-02-18 Aidan Gauland <aidalgol@no8wireless.co.nz> 132013-02-18 Aidan Gauland <aidalgol@no8wireless.co.nz>
2 14
3 * doc/misc/eshell.texi: Added documentation for Eshell insert 15 * doc/misc/eshell.texi: Added documentation for Eshell insert
diff --git a/Makefile.in b/Makefile.in
index a2de4f3b164..42b900401f7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -54,6 +54,9 @@
54# make bootstrap 54# make bootstrap
55# Removes all the compiled files to force a new bootstrap from a 55# Removes all the compiled files to force a new bootstrap from a
56# clean slate, and then build in the normal way. 56# clean slate, and then build in the normal way.
57#
58# make docs
59# Make Emacs documentation files from their sources; requires makeinfo.
57 60
58SHELL = /bin/sh 61SHELL = /bin/sh
59 62
@@ -859,13 +862,25 @@ check:
859dist: 862dist:
860 cd ${srcdir}; ./make-dist 863 cd ${srcdir}; ./make-dist
861 864
865DVIS = lispref-dvi lispintro-dvi emacs-dvi misc-dvi
866HTMLS = lispref-html lispintro-html emacs-html misc-html
867INFOS = lispref-info lispintro-info emacs-info misc-info
868PDFS = lispref-pdf lispintro-pdf emacs-pdf misc-pdf
869PSS = lispref-ps lispintro-ps emacs-ps # no misc-ps
870
871DOCS = $(DVIS) $(HTMLS) $(INFOS) $(PDFS) $(PSS)
872$(DOCS):
873 t=$@; IFS=-; set $$t; IFS=; cd doc/$$1 && $(MAKE) $(MFLAGS) $$2
874
875.PHONY: $(DOCS) docs pdf ps
862.PHONY: info dvi dist check html info-real force-info check-info-dir 876.PHONY: info dvi dist check html info-real force-info check-info-dir
863 877
864info-real: 878docs: $(DOCS)
865 (cd doc/emacs; $(MAKE) $(MFLAGS) info) 879dvi: $(DVIS)
866 (cd doc/misc; $(MAKE) $(MFLAGS) info) 880html: $(HTMLS)
867 (cd doc/lispref; $(MAKE) $(MFLAGS) info) 881info-real: $(INFOS)
868 (cd doc/lispintro; $(MAKE) $(MFLAGS) info) 882pdf: $(PDFS)
883ps: $(PSS)
869 884
870force-info: 885force-info:
871# Note that man/Makefile knows how to put the info files in $(srcdir), 886# Note that man/Makefile knows how to put the info files in $(srcdir),
@@ -904,12 +919,6 @@ check-info-dir: info
904 fi ; \ 919 fi ; \
905 echo "info/dir is OK" 920 echo "info/dir is OK"
906 921
907dvi:
908 (cd doc/emacs; $(MAKE) $(MFLAGS) dvi)
909 (cd doc/misc; $(MAKE) $(MFLAGS) dvi)
910 (cd doc/lispref; $(MAKE) $(MFLAGS) elisp.dvi)
911 (cd doc/lispintro; $(MAKE) $(MFLAGS) emacs-lisp-intro.dvi)
912
913#### Bootstrapping. 922#### Bootstrapping.
914 923
915### This first cleans the lisp subdirectory, removing all compiled 924### This first cleans the lisp subdirectory, removing all compiled
diff --git a/doc/emacs/ChangeLog b/doc/emacs/ChangeLog
index ba6f7e323e0..83d5b1d25ed 100644
--- a/doc/emacs/ChangeLog
+++ b/doc/emacs/ChangeLog
@@ -1,3 +1,7 @@
12013-02-21 Glenn Morris <rgm@gnu.org>
2
3 * files.texi (File Conveniences): Not just GIFs can be animated.
4
12013-02-13 Glenn Morris <rgm@gnu.org> 52013-02-13 Glenn Morris <rgm@gnu.org>
2 6
3 * ack.texi (Acknowledgments): Don't mention yow any more. 7 * ack.texi (Acknowledgments): Don't mention yow any more.
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index a85c16ee1bc..7f7ae483cd5 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -1937,8 +1937,7 @@ or taller than the frame, the usual point motion keys (@kbd{C-f},
1937displayed. If the image can be animated, the command @kbd{RET} 1937displayed. If the image can be animated, the command @kbd{RET}
1938(@code{image-toggle-animation}) starts or stops the animation. 1938(@code{image-toggle-animation}) starts or stops the animation.
1939Animation plays once, unless the option @code{image-animate-loop} is 1939Animation plays once, unless the option @code{image-animate-loop} is
1940non-@code{nil}. Currently, Emacs only supports animation in GIF 1940non-@code{nil}.
1941files.
1942 1941
1943@cindex ImageMagick support 1942@cindex ImageMagick support
1944@vindex imagemagick-enabled-types 1943@vindex imagemagick-enabled-types
diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index 3366ad6e7f7..3f9208c3c27 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -4583,7 +4583,7 @@ argument to the value returned by its second argument.
4583@item buffer-name 4583@item buffer-name
4584Without an argument, return the name of the buffer, as a string. 4584Without an argument, return the name of the buffer, as a string.
4585 4585
4586@itemx buffer-file-name 4586@item buffer-file-name
4587Without an argument, return the name of the file the buffer is 4587Without an argument, return the name of the file the buffer is
4588visiting. 4588visiting.
4589 4589
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog
index 74f2eb9312b..355d0b57be5 100644
--- a/doc/lispref/ChangeLog
+++ b/doc/lispref/ChangeLog
@@ -1,3 +1,7 @@
12013-02-21 Glenn Morris <rgm@gnu.org>
2
3 * display.texi (Multi-Frame Images): Minor rephrasing.
4
12013-02-20 Glenn Morris <rgm@gnu.org> 52013-02-20 Glenn Morris <rgm@gnu.org>
2 6
3 * display.texi (GIF Images, TIFF Images): Delete these nodes. 7 * display.texi (GIF Images, TIFF Images): Delete these nodes.
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 1e596c14233..eae6af9969d 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -4925,10 +4925,10 @@ integer (counting from 0) that specifies which frame is being displayed.
4925This function returns non-@code{nil} if @var{image} contains more than 4925This function returns non-@code{nil} if @var{image} contains more than
4926one frame. The actual return value is a cons @code{(@var{nimages} 4926one frame. The actual return value is a cons @code{(@var{nimages}
4927. @var{delay})}, where @var{nimages} is the number of frames and 4927. @var{delay})}, where @var{nimages} is the number of frames and
4928@var{delay} is the delay in seconds between them, if the image itself 4928@var{delay} is the delay in seconds between them, or @code{nil}
4929specifies a delay. Images that are intended to be animated usually 4929if the image does not specify a delay. Images that are intended to be
4930specify a frame delay, whereas ones that are intended to be treated as 4930animated usually specify a frame delay, whereas ones that are intended
4931multiple pages do not. 4931to be treated as multiple pages do not.
4932@end defun 4932@end defun
4933 4933
4934@defun image-current-frame image 4934@defun image-current-frame image
diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog
index 41eb17415b7..4f827073b2f 100644
--- a/doc/misc/ChangeLog
+++ b/doc/misc/ChangeLog
@@ -1,3 +1,7 @@
12013-02-21 Paul Eggert <eggert@cs.ucla.edu>
2
3 * Makefile.in (html): New rule.
4
12013-02-20 Michael Albinus <michael.albinus@gmx.de> 52013-02-20 Michael Albinus <michael.albinus@gmx.de>
2 6
3 * tramp.texi (Android shell setup): Improve. Reported by Thierry 7 * tramp.texi (Android shell setup): Improve. Reported by Thierry
diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in
index 3dac35aafee..add1b42a545 100644
--- a/doc/misc/Makefile.in
+++ b/doc/misc/Makefile.in
@@ -192,6 +192,8 @@ webhack: clean
192 192
193dvi: $(DVI_TARGETS) 193dvi: $(DVI_TARGETS)
194 194
195html: $(HTML_TARGETS)
196
195pdf: $(PDF_TARGETS) 197pdf: $(PDF_TARGETS)
196 198
197# Note that all the Info targets build the Info files in srcdir. 199# Note that all the Info targets build the Info files in srcdir.
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index 3bef6a4595c..ec01f731daf 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -83,8 +83,8 @@ handling the sort of tasks accomplished by those tools.
83* GNU Free Documentation License:: The license for this documentation. 83* GNU Free Documentation License:: The license for this documentation.
84* Concept Index:: 84* Concept Index::
85* Function and Variable Index:: 85* Function and Variable Index::
86* Key Index::
87* Command Index:: 86* Command Index::
87* Key Index::
88@end menu 88@end menu
89 89
90@node What is Eshell? 90@node What is Eshell?
@@ -285,8 +285,8 @@ history and invoking commands in a script file.
285@menu 285@menu
286* Invocation:: 286* Invocation::
287* Arguments:: 287* Arguments::
288* Variables::
289* Built-ins:: 288* Built-ins::
289* Variables::
290* Aliases:: 290* Aliases::
291* History:: 291* History::
292* Completion:: 292* Completion::
@@ -465,7 +465,7 @@ Uses TRAMP's @command{su} or @command{sudo} method to run a command via
465 465
466@end table 466@end table
467 467
468@section Built-in variables 468@subsection Built-in variables
469Eshell knows a few built-in variables: 469Eshell knows a few built-in variables:
470 470
471@table @code 471@table @code
diff --git a/doc/misc/gnus-faq.texi b/doc/misc/gnus-faq.texi
index e7367730040..ede957a5c35 100644
--- a/doc/misc/gnus-faq.texi
+++ b/doc/misc/gnus-faq.texi
@@ -3,8 +3,8 @@
3@c %**start of header 3@c %**start of header
4@c Copyright (C) 1995, 2001-2013 Free Software Foundation, Inc. 4@c Copyright (C) 1995, 2001-2013 Free Software Foundation, Inc.
5@c 5@c
6@setfilename gnus-faq.info 6@c @setfilename gnus-faq.info
7@settitle Frequently Asked Questions 7@c @settitle Frequently Asked Questions
8@c %**end of header 8@c %**end of header
9@c 9@c
10 10
@@ -41,7 +41,7 @@ Please submit features and suggestions to the
41@email{ding@@gnus.org, ding list}. 41@email{ding@@gnus.org, ding list}.
42 42
43@node FAQ - Changes 43@node FAQ - Changes
44@subheading Changes 44@subsection Changes
45 45
46 46
47 47
@@ -57,7 +57,7 @@ reference to discontinued service.
57@end itemize 57@end itemize
58 58
59@node FAQ - Introduction 59@node FAQ - Introduction
60@subheading Introduction 60@subsection Introduction
61 61
62This is the Gnus Frequently Asked Questions list. 62This is the Gnus Frequently Asked Questions list.
63 63
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 65e2ce6150e..983887d721d 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -14541,6 +14541,7 @@ maildir, for instance.
14541 14541
14542@menu 14542@menu
14543* Mail Source Specifiers:: How to specify what a mail source is. 14543* Mail Source Specifiers:: How to specify what a mail source is.
14544* Mail Source Functions::
14544* Mail Source Customization:: Some variables that influence things. 14545* Mail Source Customization:: Some variables that influence things.
14545* Fetching Mail:: Using the mail source specifiers. 14546* Fetching Mail:: Using the mail source specifiers.
14546@end menu 14547@end menu
@@ -15000,6 +15001,7 @@ useful when you use local mail and news.
15000@end table 15001@end table
15001@end table 15002@end table
15002 15003
15004@node Mail Source Functions
15003@subsubsection Function Interface 15005@subsubsection Function Interface
15004 15006
15005Some of the above keywords specify a Lisp function to be executed. 15007Some of the above keywords specify a Lisp function to be executed.
@@ -16068,6 +16070,10 @@ Spool}).
16068* Mail Spool:: Store your mail in a private spool? 16070* Mail Spool:: Store your mail in a private spool?
16069* MH Spool:: An mhspool-like back end. 16071* MH Spool:: An mhspool-like back end.
16070* Maildir:: Another one-file-per-message format. 16072* Maildir:: Another one-file-per-message format.
16073* nnmaildir Group Parameters::
16074* Article Identification::
16075* NOV Data::
16076* Article Marks::
16071* Mail Folders:: Having one file for each group. 16077* Mail Folders:: Having one file for each group.
16072* Comparing Mail Back Ends:: An in-depth looks at pros and cons. 16078* Comparing Mail Back Ends:: An in-depth looks at pros and cons.
16073@end menu 16079@end menu
@@ -16375,6 +16381,7 @@ different in the future. If your split rules create new groups,
16375remember to supply a @code{create-directory} server parameter. 16381remember to supply a @code{create-directory} server parameter.
16376@end table 16382@end table
16377 16383
16384@node nnmaildir Group Parameters
16378@subsubsection Group parameters 16385@subsubsection Group parameters
16379 16386
16380@code{nnmaildir} uses several group parameters. It's safe to ignore 16387@code{nnmaildir} uses several group parameters. It's safe to ignore
@@ -16485,6 +16492,7 @@ that are either marked with @code{tick} or not marked with
16485@code{read}, plus a little extra. 16492@code{read}, plus a little extra.
16486@end table 16493@end table
16487 16494
16495@node Article Identification
16488@subsubsection Article identification 16496@subsubsection Article identification
16489Articles are stored in the @file{cur/} subdirectory of each maildir. 16497Articles are stored in the @file{cur/} subdirectory of each maildir.
16490Each article file is named like @code{uniq:info}, where @code{uniq} 16498Each article file is named like @code{uniq:info}, where @code{uniq}
@@ -16497,6 +16505,7 @@ about the corresponding article. The full pathname of an article is
16497available in the variable @code{nnmaildir-article-file-name} after you 16505available in the variable @code{nnmaildir-article-file-name} after you
16498request the article in the summary buffer. 16506request the article in the summary buffer.
16499 16507
16508@node NOV Data
16500@subsubsection NOV data 16509@subsubsection NOV data
16501An article identified by @code{uniq} has its @acronym{NOV} data (used 16510An article identified by @code{uniq} has its @acronym{NOV} data (used
16502to generate lines in the summary buffer) stored in 16511to generate lines in the summary buffer) stored in
@@ -16510,6 +16519,7 @@ file, but @emph{beware}: this will also cause @code{nnmaildir} to
16510assign a new article number for this article, which may cause trouble 16519assign a new article number for this article, which may cause trouble
16511with @code{seen} marks, the Agent, and the cache. 16520with @code{seen} marks, the Agent, and the cache.
16512 16521
16522@node Article Marks
16513@subsubsection Article marks 16523@subsubsection Article marks
16514An article identified by @code{uniq} is considered to have the mark 16524An article identified by @code{uniq} is considered to have the mark
16515@code{flag} when the file @file{.nnmaildir/marks/flag/uniq} exists. 16525@code{flag} when the file @file{.nnmaildir/marks/flag/uniq} exists.
@@ -25850,8 +25860,8 @@ of all messages matching a particular set of criteria.
25850 25860
25851@menu 25861@menu
25852* Gnus Registry Setup:: 25862* Gnus Registry Setup::
25853* Fancy splitting to parent::
25854* Registry Article Refer Method:: 25863* Registry Article Refer Method::
25864* Fancy splitting to parent::
25855* Store custom flags and keywords:: 25865* Store custom flags and keywords::
25856* Store arbitrary data:: 25866* Store arbitrary data::
25857@end menu 25867@end menu
diff --git a/doc/misc/semantic.texi b/doc/misc/semantic.texi
index de5019ee897..f43316f5012 100644
--- a/doc/misc/semantic.texi
+++ b/doc/misc/semantic.texi
@@ -520,7 +520,7 @@ Regression tests from the older Semantic 1.x API.
520@node Glossary 520@node Glossary
521@appendix Glossary 521@appendix Glossary
522 522
523@table @keyword 523@table @asis
524@item BNF 524@item BNF
525In semantic 1.4, a BNF file represented ``Bovine Normal Form'', the 525In semantic 1.4, a BNF file represented ``Bovine Normal Form'', the
526grammar file used for the 1.4 parser generator. This was a play on 526grammar file used for the 1.4 parser generator. This was a play on
diff --git a/doc/misc/speedbar.texi b/doc/misc/speedbar.texi
index 7227e2597ae..3cb0ec3aed8 100644
--- a/doc/misc/speedbar.texi
+++ b/doc/misc/speedbar.texi
@@ -223,7 +223,7 @@ Text in speedbar consists of four different types of data. Knowing how
223to read these textual elements will make it easier to navigate by 223to read these textual elements will make it easier to navigate by
224identifying the types of data available. 224identifying the types of data available.
225 225
226@subsubsection Groups 226@subsection Groups
227@cindex groups 227@cindex groups
228 228
229Groups summarize information in a single line, and provide a high level 229Groups summarize information in a single line, and provide a high level
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index 807e6b4db29..f1dac493054 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -144,9 +144,6 @@ For the end user:
144* Usage:: An overview of the operation of @value{tramp}. 144* Usage:: An overview of the operation of @value{tramp}.
145* Bug Reports:: Reporting Bugs and Problems. 145* Bug Reports:: Reporting Bugs and Problems.
146* Frequently Asked Questions:: Questions and answers from the mailing list. 146* Frequently Asked Questions:: Questions and answers from the mailing list.
147* Function Index:: @value{tramp} functions.
148* Variable Index:: User options and variables.
149* Concept Index:: An item for each concept.
150 147
151For the developer: 148For the developer:
152 149
@@ -155,6 +152,9 @@ For the developer:
155* Issues:: Debatable Issues and What Was Decided. 152* Issues:: Debatable Issues and What Was Decided.
156 153
157* GNU Free Documentation License:: The license for this documentation. 154* GNU Free Documentation License:: The license for this documentation.
155* Function Index:: @value{tramp} functions.
156* Variable Index:: User options and variables.
157* Concept Index:: An item for each concept.
158 158
159@detailmenu 159@detailmenu
160 --- The Detailed Node Listing --- 160 --- The Detailed Node Listing ---
diff --git a/etc/MORE.STUFF b/etc/MORE.STUFF
index 57be8a2e971..671d8a06755 100644
--- a/etc/MORE.STUFF
+++ b/etc/MORE.STUFF
@@ -179,9 +179,6 @@ packages that you can install.
179 WhizzyTeX provides a minor mode for Emacs or XEmacs, a (bash) 179 WhizzyTeX provides a minor mode for Emacs or XEmacs, a (bash)
180 shell-script daemon and some LaTeX macros. 180 shell-script daemon and some LaTeX macros.
181 181
182 * X-Symbol: <URL:http://x-symbol.sourceforge.net/>
183 Quasi-WYSIWYG editing of TeX & al.
184
185Local Variables: 182Local Variables:
186mode: text 183mode: text
187eval: (view-mode 1) 184eval: (view-mode 1)
diff --git a/etc/NEWS b/etc/NEWS
index 2eda7a5c775..d6691ffed8f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -145,8 +145,6 @@ directory, respectively.
145`f' (`image-next-frame') and `b' (`image-previous-frame') visit the 145`f' (`image-next-frame') and `b' (`image-previous-frame') visit the
146next or previous frame. `F' (`image-goto-frame') shows a specific frame. 146next or previous frame. `F' (`image-goto-frame') shows a specific frame.
147 147
148*** `image-animated-p' is now `image-multi-frame-p'.
149
150--- 148---
151*** The command `image-mode-fit-frame' deletes other windows. 149*** The command `image-mode-fit-frame' deletes other windows.
152When toggling, it restores the frame's previous window configuration. 150When toggling, it restores the frame's previous window configuration.
@@ -220,6 +218,10 @@ are obsolete. Customize the `woman-* faces instead.
220+++ 218+++
221*** yow.el is obsolete; use fortune.el or cookie1.el instead. 219*** yow.el is obsolete; use fortune.el or cookie1.el instead.
222 220
221---
222*** The Info-edit command is obsolete. Editing Info nodes by hand
223has not been relevant for some time.
224
223 225
224* New Modes and Packages in Emacs 24.4 226* New Modes and Packages in Emacs 24.4
225** New nadvice.el package offering lighter-weight advice facilities. 227** New nadvice.el package offering lighter-weight advice facilities.
@@ -291,6 +293,21 @@ rather than inheriting from it (as do face specs set via Customize).
291*** New face characteristic (supports :underline (:style wave)) 293*** New face characteristic (supports :underline (:style wave))
292specifies whether or not the terminal can display a wavy line. 294specifies whether or not the terminal can display a wavy line.
293 295
296** Image API
297
298+++
299*** `image-animated-p' is now `image-multi-frame-p'.
300It returns non-nil for any image that contains multiple frames,
301whether or not it specifies a frame delay.
302
303+++
304*** When animating images that do not specify a frame delay,
305Emacs uses `image-default-frame-delay'.
306
307+++
308*** New functions `image-current-frame' and `image-show-frame' for getting
309and setting the current frame of a multi-frame image.
310
294** time-to-seconds is not obsolete any more. 311** time-to-seconds is not obsolete any more.
295** New function special-form-p. 312** New function special-form-p.
296** Docstrings can be made dynamic by adding a `dynamic-docstring-function' 313** Docstrings can be made dynamic by adding a `dynamic-docstring-function'
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index abcf6578060..68cff2f6d29 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,49 @@
12013-02-21 Bastien Guerry <bzg@gnu.org>
2
3 * cmuscheme.el (scheme-buffer): Fix docstring. (Bug#13778)
4
52013-02-21 Fabián Ezequiel Gallina <fgallina@cuca>
6
7 * progmodes/python.el (python-info-current-defun): Enhance
8 match-data cluttering prevention.
9
102013-02-21 Glenn Morris <rgm@gnu.org>
11
12 * net/tramp.el (tramp-get-debug-buffer): Ensure outline.el is not
13 loaded while outline-regexp is let bound. (Bug#9584)
14
152013-02-21 Fabián Ezequiel Gallina <fgallina@cuca>
16
17 * progmodes/python.el (python-info-current-defun): Fix failed
18 defun name retrieval because of unwanted match-data cluttering.
19
202013-02-21 Michael Albinus <michael.albinus@gmx.de>
21
22 * net/tramp.el (tramp-ssh-controlmaster-template): Make it a
23 defconst. Apply independent check for ControlPersist.
24
25 * net/tramp-sh.el (tramp-sh-handle-set-file-times): Set $UTC only
26 temporarily, via "env".
27
282013-02-21 Glenn Morris <rgm@gnu.org>
29
30 * info.el (Info-enable-edit): Remove.
31 (Info-edit): Disable it rather than using Info-enable.
32 (Info-edit-mode-hook, Info-edit-map, Info-edit-mode, Info-edit)
33 (Info-cease-edit): Make editing of Info files obsolete.
34
35 * informat.el (Info-tagify):
36 Handle buffers not visiting files. (Bug#13763)
37
382013-02-21 Juanma Barranquero <lekktu@gmail.com>
39
40 * calc/calc-graph.el (calc-graph-show-dumb): Fix typo.
41
422013-02-21 Glenn Morris <rgm@gnu.org>
43
44 * files.el (basic-save-buffer): Move check for existing parent
45 directory after hooks. (Bug#13773)
46
12013-02-20 Stefan Monnier <monnier@iro.umontreal.ca> 472013-02-20 Stefan Monnier <monnier@iro.umontreal.ca>
2 48
3 * simple.el (command-execute): Move from C. Add obsolete check. 49 * simple.el (command-execute): Move from C. Add obsolete check.
diff --git a/lisp/calc/calc-graph.el b/lisp/calc/calc-graph.el
index c84c7fdf949..16fc6c09dbe 100644
--- a/lisp/calc/calc-graph.el
+++ b/lisp/calc/calc-graph.el
@@ -948,7 +948,7 @@ This \"dumb\" driver will be present in Gnuplot 3.0."
948 (setq calc-dumb-map (make-sparse-keymap)) 948 (setq calc-dumb-map (make-sparse-keymap))
949 (define-key calc-dumb-map "\n" 'scroll-up-command) 949 (define-key calc-dumb-map "\n" 'scroll-up-command)
950 (define-key calc-dumb-map " " 'scroll-up-command) 950 (define-key calc-dumb-map " " 'scroll-up-command)
951 (define-key calc-dump-map [?\S-\ ] 'scroll-down-command) 951 (define-key calc-dumb-map [?\S-\ ] 'scroll-down-command)
952 (define-key calc-dumb-map "\177" 'scroll-down-command) 952 (define-key calc-dumb-map "\177" 'scroll-down-command)
953 (define-key calc-dumb-map "<" 'scroll-left) 953 (define-key calc-dumb-map "<" 'scroll-left)
954 (define-key calc-dumb-map ">" 'scroll-right) 954 (define-key calc-dumb-map ">" 'scroll-right)
diff --git a/lisp/cmuscheme.el b/lisp/cmuscheme.el
index d40822188ee..130eb374538 100644
--- a/lisp/cmuscheme.el
+++ b/lisp/cmuscheme.el
@@ -447,7 +447,7 @@ in the next one.")
447 "\"\)\n"))) 447 "\"\)\n")))
448 448
449 449
450(defvar scheme-buffer nil "*The current scheme process buffer. 450(defvar scheme-buffer nil "The current scheme process buffer.
451 451
452MULTIPLE PROCESS SUPPORT 452MULTIPLE PROCESS SUPPORT
453=========================================================================== 453===========================================================================
diff --git a/lisp/files.el b/lisp/files.el
index f9ed65b8ac0..f9d02511839 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -4563,15 +4563,8 @@ Before and after saving the buffer, this function runs
4563 (not (file-exists-p buffer-file-name)))) 4563 (not (file-exists-p buffer-file-name))))
4564 (let ((recent-save (recent-auto-save-p)) 4564 (let ((recent-save (recent-auto-save-p))
4565 setmodes) 4565 setmodes)
4566 (if buffer-file-name
4567 (let ((dir (file-name-directory
4568 (expand-file-name buffer-file-name))))
4569 (unless (file-exists-p dir)
4570 (if (y-or-n-p
4571 (format "Directory `%s' does not exist; create? " dir))
4572 (make-directory dir t)
4573 (error "Canceled"))))
4574 ;; If buffer has no file name, ask user for one. 4566 ;; If buffer has no file name, ask user for one.
4567 (or buffer-file-name
4575 (let ((filename 4568 (let ((filename
4576 (expand-file-name 4569 (expand-file-name
4577 (read-file-name "File to save in: " 4570 (read-file-name "File to save in: "
@@ -4628,7 +4621,14 @@ Before and after saving the buffer, this function runs
4628 (run-hook-with-args-until-success 'write-file-functions) 4621 (run-hook-with-args-until-success 'write-file-functions)
4629 ;; If a hook returned t, file is already "written". 4622 ;; If a hook returned t, file is already "written".
4630 ;; Otherwise, write it the usual way now. 4623 ;; Otherwise, write it the usual way now.
4631 (setq setmodes (basic-save-buffer-1))) 4624 (let ((dir (file-name-directory
4625 (expand-file-name buffer-file-name))))
4626 (unless (file-exists-p dir)
4627 (if (y-or-n-p
4628 (format "Directory `%s' does not exist; create? " dir))
4629 (make-directory dir t)
4630 (error "Canceled")))
4631 (setq setmodes (basic-save-buffer-1))))
4632 ;; Now we have saved the current buffer. Let's make sure 4632 ;; Now we have saved the current buffer. Let's make sure
4633 ;; that buffer-file-coding-system is fixed to what 4633 ;; that buffer-file-coding-system is fixed to what
4634 ;; actually used for saving by binding it locally. 4634 ;; actually used for saving by binding it locally.
diff --git a/lisp/info.el b/lisp/info.el
index 24a7181ff52..3792857d47a 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -59,15 +59,6 @@ to the user."
59 :group 'info 59 :group 'info
60 :version "24.1") 60 :version "24.1")
61 61
62(defcustom Info-enable-edit nil
63 "Non-nil means the \\<Info-mode-map>\\[Info-edit] command in Info can edit the current node.
64This is convenient if you want to write Info files by hand.
65However, we recommend that you not do this.
66It is better to write a Texinfo file and generate the Info file from that,
67because that gives you a printed manual as well."
68 :type 'boolean
69 :group 'info)
70
71(defvar Info-enable-active-nodes nil 62(defvar Info-enable-active-nodes nil
72 "Non-nil allows Info to execute Lisp code associated with nodes. 63 "Non-nil allows Info to execute Lisp code associated with nodes.
73The Lisp code is executed when the node is selected.") 64The Lisp code is executed when the node is selected.")
@@ -375,6 +366,9 @@ with wrapping around the current Info node."
375(defvar Info-edit-mode-hook nil 366(defvar Info-edit-mode-hook nil
376 "Hooks run when `Info-edit-mode' is called.") 367 "Hooks run when `Info-edit-mode' is called.")
377 368
369(make-obsolete-variable 'Info-edit-mode-hook
370 "editing Info nodes by hand is not recommended." "24.4")
371
378(defvar Info-current-file nil 372(defvar Info-current-file nil
379 "Info file that Info is now looking at, or nil. 373 "Info file that Info is now looking at, or nil.
380This is the name that was specified in Info, not the actual file name. 374This is the name that was specified in Info, not the actual file name.
@@ -4253,6 +4247,10 @@ Advanced commands:
4253 map) 4247 map)
4254 "Local keymap used within `e' command of Info.") 4248 "Local keymap used within `e' command of Info.")
4255 4249
4250(make-obsolete-variable 'Info-edit-map
4251 "editing Info nodes by hand is not recommended."
4252 "24.4")
4253
4256;; Info-edit mode is suitable only for specially formatted data. 4254;; Info-edit mode is suitable only for specially formatted data.
4257(put 'Info-edit-mode 'mode-class 'special) 4255(put 'Info-edit-mode 'mode-class 'special)
4258 4256
@@ -4270,16 +4268,22 @@ which returns to Info mode for browsing.
4270 (buffer-enable-undo (current-buffer)) 4268 (buffer-enable-undo (current-buffer))
4271 (run-mode-hooks 'Info-edit-mode-hook)) 4269 (run-mode-hooks 'Info-edit-mode-hook))
4272 4270
4271(make-obsolete 'Info-edit-mode
4272 "editing Info nodes by hand is not recommended." "24.4")
4273
4273(defun Info-edit () 4274(defun Info-edit ()
4274 "Edit the contents of this Info node. 4275 "Edit the contents of this Info node."
4275Allowed only if variable `Info-enable-edit' is non-nil."
4276 (interactive) 4276 (interactive)
4277 (or Info-enable-edit
4278 (error "Editing Info nodes is not enabled"))
4279 (Info-edit-mode) 4277 (Info-edit-mode)
4280 (message "%s" (substitute-command-keys 4278 (message "%s" (substitute-command-keys
4281 "Editing: Type \\<Info-edit-map>\\[Info-cease-edit] to return to info"))) 4279 "Editing: Type \\<Info-edit-map>\\[Info-cease-edit] to return to info")))
4282 4280
4281(put 'Info-edit 'disabled "Editing Info nodes by hand is not recommended.
4282This feature will be removed in future.")
4283
4284(make-obsolete 'Info-edit
4285 "editing Info nodes by hand is not recommended." "24.4")
4286
4283(defun Info-cease-edit () 4287(defun Info-cease-edit ()
4284 "Finish editing Info node; switch back to Info proper." 4288 "Finish editing Info node; switch back to Info proper."
4285 (interactive) 4289 (interactive)
@@ -4296,6 +4300,9 @@ Allowed only if variable `Info-enable-edit' is non-nil."
4296 (and (marker-position Info-tag-table-marker) 4300 (and (marker-position Info-tag-table-marker)
4297 (buffer-modified-p) 4301 (buffer-modified-p)
4298 (message "Tags may have changed. Use Info-tagify if necessary"))) 4302 (message "Tags may have changed. Use Info-tagify if necessary")))
4303
4304(make-obsolete 'Info-cease-edit
4305 "editing Info nodes by hand is not recommended." "24.4")
4299 4306
4300(defvar Info-file-list-for-emacs 4307(defvar Info-file-list-for-emacs
4301 '("ediff" "eudc" "forms" "gnus" "info" ("Info" . "info") ("mh" . "mh-e") 4308 '("ediff" "eudc" "forms" "gnus" "info" ("Info" . "info") ("mh" . "mh-e")
diff --git a/lisp/informat.el b/lisp/informat.el
index d4412b8a86a..53b043fbbad 100644
--- a/lisp/informat.el
+++ b/lisp/informat.el
@@ -43,14 +43,17 @@
43 ;; save-restrictions would not work 43 ;; save-restrictions would not work
44 ;; because it records the old max relative to the end. 44 ;; because it records the old max relative to the end.
45 ;; We record it relative to the beginning. 45 ;; We record it relative to the beginning.
46 (if input-buffer-name
47 (message "Tagifying region in %s ..." input-buffer-name)
48 (message
49 "Tagifying %s ..." (file-name-nondirectory (buffer-file-name))))
50 (let ((omin (point-min)) 46 (let ((omin (point-min))
51 (omax (point-max)) 47 (omax (point-max))
52 (nomax (= (point-max) (1+ (buffer-size)))) 48 (nomax (= (point-max) (1+ (buffer-size))))
53 (opoint (point))) 49 (opoint (point))
50 (msg (format "Tagifying %s..."
51 (cond (input-buffer-name
52 (format "region in %s" input-buffer-name))
53 (buffer-file-name
54 (file-name-nondirectory (buffer-file-name)))
55 (t "buffer")))))
56 (message "%s" msg)
54 (unwind-protect 57 (unwind-protect
55 (progn 58 (progn
56 (widen) 59 (widen)
@@ -148,11 +151,8 @@
148 (insert "\^_\nEnd tag table\n"))))) 151 (insert "\^_\nEnd tag table\n")))))
149 (goto-char opoint) 152 (goto-char opoint)
150 (narrow-to-region omin (if nomax (1+ (buffer-size)) 153 (narrow-to-region omin (if nomax (1+ (buffer-size))
151 (min omax (point-max)))))) 154 (min omax (point-max)))))
152 (if input-buffer-name 155 (message "%sdone" msg)))
153 (message "Tagifying region in %s done" input-buffer-name)
154 (message
155 "Tagifying %s done" (file-name-nondirectory (buffer-file-name)))))
156 156
157 157
158;;;###autoload 158;;;###autoload
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 7388c570874..82cbda57086 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1410,7 +1410,7 @@ of."
1410 (utc (not (featurep 'xemacs)))) 1410 (utc (not (featurep 'xemacs))))
1411 (tramp-send-command-and-check 1411 (tramp-send-command-and-check
1412 v (format "%s touch -t %s %s" 1412 v (format "%s touch -t %s %s"
1413 (if utc "TZ=UTC; export TZ;" "") 1413 (if utc "env TZ=UTC" "")
1414 (if utc 1414 (if utc
1415 (format-time-string "%Y%m%d%H%M.%S" time t) 1415 (format-time-string "%Y%m%d%H%M.%S" time t)
1416 (format-time-string "%Y%m%d%H%M.%S" time)) 1416 (format-time-string "%Y%m%d%H%M.%S" time))
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 89648b0e9a9..4bfe541f053 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -281,16 +281,24 @@ started on the local host. You should specify a remote host
281useful only in combination with `tramp-default-proxies-alist'.") 281useful only in combination with `tramp-default-proxies-alist'.")
282 282
283;;;###tramp-autoload 283;;;###tramp-autoload
284(defvar tramp-ssh-controlmaster-template 284(defconst tramp-ssh-controlmaster-template
285 (let (result)
285 (ignore-errors 286 (ignore-errors
286 (with-temp-buffer 287 (with-temp-buffer
287 (call-process "ssh" nil t nil "-o" "ControlMaster") 288 (call-process "ssh" nil t nil "-o" "ControlMaster")
288 (goto-char (point-min)) 289 (goto-char (point-min))
289 (when (search-forward-regexp "Missing ControlMaster argument" nil t) 290 (when (search-forward-regexp "Missing ControlMaster argument" nil t)
290 '("-o" "ControlPath=%t.%%r@%%h:%%p" 291 (setq result
291 "-o" "ControlMaster=auto" 292 '("-o" "ControlPath=%t.%%r@%%h:%%p"
292 "-o" "ControlPersist=no")))) 293 "-o" "ControlMaster=auto"))))
293 "Call ssh to detect whether it supports the ControlMaster argument. 294 (when result
295 (with-temp-buffer
296 (call-process "ssh" nil t nil "-o" "ControlPersist")
297 (goto-char (point-min))
298 (when (search-forward-regexp "Missing ControlPersist argument" nil t)
299 (setq result (append result '("-o" "ControlPersist=no")))))))
300 result)
301 "Call ssh to detect whether it supports the Control* arguments.
294Return a template to be used in `tramp-methods'.") 302Return a template to be used in `tramp-methods'.")
295 303
296(defcustom tramp-default-method 304(defcustom tramp-default-method
@@ -1346,6 +1354,8 @@ The outline level is equal to the verbosity of the Tramp message."
1346 (get-buffer-create (tramp-debug-buffer-name vec)) 1354 (get-buffer-create (tramp-debug-buffer-name vec))
1347 (when (bobp) 1355 (when (bobp)
1348 (setq buffer-undo-list t) 1356 (setq buffer-undo-list t)
1357 ;; So it does not get loaded while outline-regexp is let-bound.
1358 (require 'outline)
1349 ;; Activate `outline-mode'. This runs `text-mode-hook' and 1359 ;; Activate `outline-mode'. This runs `text-mode-hook' and
1350 ;; `outline-mode-hook'. We must prevent that local processes 1360 ;; `outline-mode-hook'. We must prevent that local processes
1351 ;; die. Yes: I've seen `flyspell-mode', which starts "ispell". 1361 ;; die. Yes: I've seen `flyspell-mode', which starts "ispell".
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index da56fe70329..f0f67d01845 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -2959,39 +2959,40 @@ not inside a defun."
2959 (type)) 2959 (type))
2960 (catch 'exit 2960 (catch 'exit
2961 (while (python-nav-beginning-of-defun 1) 2961 (while (python-nav-beginning-of-defun 1)
2962 (when (and 2962 (when (save-match-data
2963 (or (not last-indent) 2963 (and
2964 (< (current-indentation) last-indent)) 2964 (or (not last-indent)
2965 (or 2965 (< (current-indentation) last-indent))
2966 (and first-run 2966 (or
2967 (and first-run
2968 (save-excursion
2969 ;; If this is the first run, we may add
2970 ;; the current defun at point.
2971 (setq first-run nil)
2972 (goto-char starting-pos)
2973 (python-nav-beginning-of-statement)
2974 (beginning-of-line 1)
2975 (looking-at-p
2976 python-nav-beginning-of-defun-regexp)))
2977 (< starting-pos
2967 (save-excursion 2978 (save-excursion
2968 ;; If this is the first run, we may add 2979 (let ((min-indent
2969 ;; the current defun at point. 2980 (+ (current-indentation)
2970 (setq first-run nil) 2981 python-indent-offset)))
2971 (goto-char starting-pos) 2982 (if (< starting-indentation min-indent)
2972 (python-nav-beginning-of-statement) 2983 ;; If the starting indentation is not
2973 (beginning-of-line 1) 2984 ;; within the min defun indent make the
2974 (looking-at-p 2985 ;; check fail.
2975 python-nav-beginning-of-defun-regexp))) 2986 starting-pos
2976 (< starting-pos 2987 ;; Else go to the end of defun and add
2977 (save-excursion 2988 ;; up the current indentation to the
2978 (let ((min-indent 2989 ;; ending position.
2979 (+ (current-indentation) 2990 (python-nav-end-of-defun)
2980 python-indent-offset))) 2991 (+ (point)
2981 (if (< starting-indentation min-indent) 2992 (if (>= (current-indentation) min-indent)
2982 ;; If the starting indentation is not 2993 (1+ (current-indentation))
2983 ;; within the min defun indent make the 2994 0)))))))))
2984 ;; check fail. 2995 (save-match-data (setq last-indent (current-indentation)))
2985 starting-pos
2986 ;; Else go to the end of defun and add
2987 ;; up the current indentation to the
2988 ;; ending position.
2989 (python-nav-end-of-defun)
2990 (+ (point)
2991 (if (>= (current-indentation) min-indent)
2992 (1+ (current-indentation))
2993 0))))))))
2994 (setq last-indent (current-indentation))
2995 (if (or (not include-type) type) 2996 (if (or (not include-type) type)
2996 (setq names (cons (match-string-no-properties 1) names)) 2997 (setq names (cons (match-string-no-properties 1) names))
2997 (let ((match (split-string (match-string-no-properties 0)))) 2998 (let ((match (split-string (match-string-no-properties 0))))
diff --git a/src/ChangeLog b/src/ChangeLog
index d39336f11e6..ff45c4b2a83 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
12013-02-21 Ken Brown <kbrown@cornell.edu>
2
3 * sheap.c (report_sheap_usage): Fix arguments of message1_no_log.
4
12013-02-20 Stefan Monnier <monnier@iro.umontreal.ca> 52013-02-20 Stefan Monnier <monnier@iro.umontreal.ca>
2 6
3 * sheap.c (report_sheap_usage): Prefer message1_nolog. 7 * sheap.c (report_sheap_usage): Prefer message1_nolog.
diff --git a/src/sheap.c b/src/sheap.c
index 28597ec9b65..f8eec753268 100644
--- a/src/sheap.c
+++ b/src/sheap.c
@@ -93,5 +93,5 @@ report_sheap_usage (int die_if_pure_storage_exceeded)
93 bss_sbrk_ptr - bss_sbrk_buffer, STATIC_HEAP_SIZE); 93 bss_sbrk_ptr - bss_sbrk_buffer, STATIC_HEAP_SIZE);
94 /* Don't log messages, cause at this point, we're not allowed to create 94 /* Don't log messages, cause at this point, we're not allowed to create
95 buffers. */ 95 buffers. */
96 message1_nolog ("%s", buf); 96 message1_nolog (buf);
97} 97}
diff --git a/test/ChangeLog b/test/ChangeLog
index 7fed4f29408..f1281c8ed72 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,7 @@
12013-02-21 Fabián Ezequiel Gallina <fgallina@cuca>
2
3 * automated/python-tests.el: New file.
4
12013-02-14 Dmitry Gutov <dgutov@yandex.ru> 52013-02-14 Dmitry Gutov <dgutov@yandex.ru>
2 6
3 * automated/ruby-mode-tests.el 7 * automated/ruby-mode-tests.el
diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el
new file mode 100644
index 00000000000..8dd15ffbaa7
--- /dev/null
+++ b/test/automated/python-tests.el
@@ -0,0 +1,1947 @@
1;;; python-tests.el --- Test suite for python.el
2
3;; Copyright (C) 2013 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
19
20;;; Commentary:
21
22;;; Code:
23
24(require 'python)
25
26(defmacro python-tests-with-temp-buffer (contents &rest body)
27 "Create a `python-mode' enabeld temp buffer with CONTENTS.
28BODY is code to be executed within the temp buffer. Point is
29always located at the beginning of buffer."
30 (declare (indent 1) (debug t))
31 `(with-temp-buffer
32 (python-mode)
33 (insert ,contents)
34 (goto-char (point-min))
35 ,@body))
36
37(defun python-tests-look-at (string &optional num restore-point)
38 "Move point at beginning of STRING in the current buffer.
39Optional argument NUM defaults to 1 and is an integer indicating
40how many ocurrences must be found, when positive the search is
41done forwards, otherwise backwards. When RESTORE-POINT is
42non-nil the point is not moved but the position found is still
43returned. When searching forward and point is already looking at
44STRING, it is skipped so the next STRING occurrence is selected."
45 (let* ((num (or num 1))
46 (starting-point (point))
47 (string (regexp-quote string))
48 (search-fn (if (> num 0) #'re-search-forward #'re-search-backward))
49 (deinc-fn (if (> num 0) #'1- #'1+))
50 (found-point))
51 (prog2
52 (catch 'exit
53 (while (not (= num 0))
54 (when (and (> num 0)
55 (looking-at string))
56 ;; Moving forward and already looking at STRING, skip it.
57 (forward-char (length (match-string-no-properties 0))))
58 (and (not (funcall search-fn string nil t))
59 (throw 'exit t))
60 (when (> num 0)
61 ;; `re-search-forward' leaves point at the end of the
62 ;; occurrence, move back so point is at the beginning
63 ;; instead.
64 (forward-char (- (length (match-string-no-properties 0)))))
65 (setq
66 num (funcall deinc-fn num)
67 found-point (point))))
68 found-point
69 (and restore-point (goto-char starting-point)))))
70
71
72;;; Tests for your tests, so you can test while you test.
73
74(ert-deftest python-tests-look-at-1 ()
75 "Test forward movement."
76 (python-tests-with-temp-buffer
77 "Lorem ipsum dolor sit amet, consectetur adipisicing elit,
78sed do eiusmod tempor incididunt ut labore et dolore magna
79aliqua."
80 (let ((expected (save-excursion
81 (dotimes (i 3)
82 (re-search-forward "et" nil t))
83 (forward-char -2)
84 (point))))
85 (should (= (python-tests-look-at "et" 3 t) expected))
86 ;; Even if NUM is bigger than found occurrences the point of last
87 ;; one should be returned.
88 (should (= (python-tests-look-at "et" 6 t) expected))
89 ;; If already looking at STRING, it should skip it.
90 (dotimes (i 2) (re-search-forward "et"))
91 (forward-char -2)
92 (should (= (python-tests-look-at "et") expected)))))
93
94(ert-deftest python-tests-look-at-2 ()
95 "Test backward movement."
96 (python-tests-with-temp-buffer
97 "Lorem ipsum dolor sit amet, consectetur adipisicing elit,
98sed do eiusmod tempor incididunt ut labore et dolore magna
99aliqua."
100 (let ((expected
101 (save-excursion
102 (re-search-forward "et" nil t)
103 (forward-char -2)
104 (point))))
105 (dotimes (i 3)
106 (re-search-forward "et" nil t))
107 (should (= (python-tests-look-at "et" -3 t) expected))
108 (should (= (python-tests-look-at "et" -6 t) expected)))))
109
110
111;;; Bindings
112
113
114;;; Python specialized rx
115
116
117;;; Font-lock and syntax
118
119
120;;; Indentation
121
122;; See: http://www.python.org/dev/peps/pep-0008/#indentation
123
124(ert-deftest python-indent-pep8-1 ()
125 "First pep8 case."
126 (python-tests-with-temp-buffer
127 "# Aligned with opening delimiter
128foo = long_function_name(var_one, var_two,
129 var_three, var_four)
130"
131 (should (eq (car (python-indent-context)) 'no-indent))
132 (should (= (python-indent-calculate-indentation) 0))
133 (python-tests-look-at "foo = long_function_name(var_one, var_two,")
134 (should (eq (car (python-indent-context)) 'after-line))
135 (should (= (python-indent-calculate-indentation) 0))
136 (python-tests-look-at "var_three, var_four)")
137 (should (eq (car (python-indent-context)) 'inside-paren))
138 (should (= (python-indent-calculate-indentation) 25))))
139
140(ert-deftest python-indent-pep8-2 ()
141 "Second pep8 case."
142 (python-tests-with-temp-buffer
143 "# More indentation included to distinguish this from the rest.
144def long_function_name(
145 var_one, var_two, var_three,
146 var_four):
147 print (var_one)
148"
149 (should (eq (car (python-indent-context)) 'no-indent))
150 (should (= (python-indent-calculate-indentation) 0))
151 (python-tests-look-at "def long_function_name(")
152 (should (eq (car (python-indent-context)) 'after-line))
153 (should (= (python-indent-calculate-indentation) 0))
154 (python-tests-look-at "var_one, var_two, var_three,")
155 (should (eq (car (python-indent-context)) 'inside-paren))
156 (should (= (python-indent-calculate-indentation) 8))
157 (python-tests-look-at "var_four):")
158 (should (eq (car (python-indent-context)) 'inside-paren))
159 (should (= (python-indent-calculate-indentation) 8))
160 (python-tests-look-at "print (var_one)")
161 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
162 (should (= (python-indent-calculate-indentation) 4))))
163
164(ert-deftest python-indent-pep8-3 ()
165 "Third pep8 case."
166 (python-tests-with-temp-buffer
167 "# Extra indentation is not necessary.
168foo = long_function_name(
169 var_one, var_two,
170 var_three, var_four)
171"
172 (should (eq (car (python-indent-context)) 'no-indent))
173 (should (= (python-indent-calculate-indentation) 0))
174 (python-tests-look-at "foo = long_function_name(")
175 (should (eq (car (python-indent-context)) 'after-line))
176 (should (= (python-indent-calculate-indentation) 0))
177 (python-tests-look-at "var_one, var_two,")
178 (should (eq (car (python-indent-context)) 'inside-paren))
179 (should (= (python-indent-calculate-indentation) 4))
180 (python-tests-look-at "var_three, var_four)")
181 (should (eq (car (python-indent-context)) 'inside-paren))
182 (should (= (python-indent-calculate-indentation) 4))))
183
184(ert-deftest python-indent-inside-paren-1 ()
185 "The most simple inside-paren case that shouldn't fail."
186 (python-tests-with-temp-buffer
187 "
188data = {
189 'key':
190 {
191 'objlist': [
192 {
193 'pk': 1,
194 'name': 'first',
195 },
196 {
197 'pk': 2,
198 'name': 'second',
199 }
200 ]
201 }
202}
203"
204 (python-tests-look-at "data = {")
205 (should (eq (car (python-indent-context)) 'after-line))
206 (should (= (python-indent-calculate-indentation) 0))
207 (python-tests-look-at "'key':")
208 (should (eq (car (python-indent-context)) 'inside-paren))
209 (should (= (python-indent-calculate-indentation) 4))
210 (python-tests-look-at "{")
211 (should (eq (car (python-indent-context)) 'inside-paren))
212 (should (= (python-indent-calculate-indentation) 4))
213 (python-tests-look-at "'objlist': [")
214 (should (eq (car (python-indent-context)) 'inside-paren))
215 (should (= (python-indent-calculate-indentation) 8))
216 (python-tests-look-at "{")
217 (should (eq (car (python-indent-context)) 'inside-paren))
218 (should (= (python-indent-calculate-indentation) 12))
219 (python-tests-look-at "'pk': 1,")
220 (should (eq (car (python-indent-context)) 'inside-paren))
221 (should (= (python-indent-calculate-indentation) 16))
222 (python-tests-look-at "'name': 'first',")
223 (should (eq (car (python-indent-context)) 'inside-paren))
224 (should (= (python-indent-calculate-indentation) 16))
225 (python-tests-look-at "},")
226 (should (eq (car (python-indent-context)) 'inside-paren))
227 (should (= (python-indent-calculate-indentation) 12))
228 (python-tests-look-at "{")
229 (should (eq (car (python-indent-context)) 'inside-paren))
230 (should (= (python-indent-calculate-indentation) 12))
231 (python-tests-look-at "'pk': 2,")
232 (should (eq (car (python-indent-context)) 'inside-paren))
233 (should (= (python-indent-calculate-indentation) 16))
234 (python-tests-look-at "'name': 'second',")
235 (should (eq (car (python-indent-context)) 'inside-paren))
236 (should (= (python-indent-calculate-indentation) 16))
237 (python-tests-look-at "}")
238 (should (eq (car (python-indent-context)) 'inside-paren))
239 (should (= (python-indent-calculate-indentation) 12))
240 (python-tests-look-at "]")
241 (should (eq (car (python-indent-context)) 'inside-paren))
242 (should (= (python-indent-calculate-indentation) 8))
243 (python-tests-look-at "}")
244 (should (eq (car (python-indent-context)) 'inside-paren))
245 (should (= (python-indent-calculate-indentation) 4))
246 (python-tests-look-at "}")
247 (should (eq (car (python-indent-context)) 'inside-paren))
248 (should (= (python-indent-calculate-indentation) 0))))
249
250(ert-deftest python-indent-inside-paren-2 ()
251 "Another more compact paren group style."
252 (python-tests-with-temp-buffer
253 "
254data = {'key': {
255 'objlist': [
256 {'pk': 1,
257 'name': 'first'},
258 {'pk': 2,
259 'name': 'second'}
260 ]
261}}
262"
263 (python-tests-look-at "data = {")
264 (should (eq (car (python-indent-context)) 'after-line))
265 (should (= (python-indent-calculate-indentation) 0))
266 (python-tests-look-at "'objlist': [")
267 (should (eq (car (python-indent-context)) 'inside-paren))
268 (should (= (python-indent-calculate-indentation) 4))
269 (python-tests-look-at "{'pk': 1,")
270 (should (eq (car (python-indent-context)) 'inside-paren))
271 (should (= (python-indent-calculate-indentation) 8))
272 (python-tests-look-at "'name': 'first'},")
273 (should (eq (car (python-indent-context)) 'inside-paren))
274 (should (= (python-indent-calculate-indentation) 9))
275 (python-tests-look-at "{'pk': 2,")
276 (should (eq (car (python-indent-context)) 'inside-paren))
277 (should (= (python-indent-calculate-indentation) 8))
278 (python-tests-look-at "'name': 'second'}")
279 (should (eq (car (python-indent-context)) 'inside-paren))
280 (should (= (python-indent-calculate-indentation) 9))
281 (python-tests-look-at "]")
282 (should (eq (car (python-indent-context)) 'inside-paren))
283 (should (= (python-indent-calculate-indentation) 4))
284 (python-tests-look-at "}}")
285 (should (eq (car (python-indent-context)) 'inside-paren))
286 (should (= (python-indent-calculate-indentation) 0))
287 (python-tests-look-at "}")
288 (should (eq (car (python-indent-context)) 'inside-paren))
289 (should (= (python-indent-calculate-indentation) 0))))
290
291(ert-deftest python-indent-after-block-1 ()
292 "The most simple after-block case that shouldn't fail."
293 (python-tests-with-temp-buffer
294 "
295def foo(a, b, c=True):
296"
297 (should (eq (car (python-indent-context)) 'no-indent))
298 (should (= (python-indent-calculate-indentation) 0))
299 (goto-char (point-max))
300 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
301 (should (= (python-indent-calculate-indentation) 4))))
302
303(ert-deftest python-indent-after-block-2 ()
304 "A weird (malformed) multiline block statement."
305 (python-tests-with-temp-buffer
306 "
307def foo(a, b, c={
308 'a':
309}):
310"
311 (goto-char (point-max))
312 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
313 (should (= (python-indent-calculate-indentation) 4))))
314
315(ert-deftest python-indent-dedenters-1 ()
316 "Check all dedenters."
317 (python-tests-with-temp-buffer
318 "
319def foo(a, b, c):
320 if a:
321 print (a)
322 elif b:
323 print (b)
324 else:
325 try:
326 print (c.pop())
327 except (IndexError, AttributeError):
328 print (c)
329 finally:
330 print ('nor a, nor b are true')
331"
332 (python-tests-look-at "if a:")
333 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
334 (should (= (python-indent-calculate-indentation) 4))
335 (python-tests-look-at "print (a)")
336 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
337 (should (= (python-indent-calculate-indentation) 8))
338 (python-tests-look-at "elif b:")
339 (should (eq (car (python-indent-context)) 'after-line))
340 (should (= (python-indent-calculate-indentation) 4))
341 (python-tests-look-at "print (b)")
342 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
343 (should (= (python-indent-calculate-indentation) 8))
344 (python-tests-look-at "else:")
345 (should (eq (car (python-indent-context)) 'after-line))
346 (should (= (python-indent-calculate-indentation) 4))
347 (python-tests-look-at "try:")
348 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
349 (should (= (python-indent-calculate-indentation) 8))
350 (python-tests-look-at "print (c.pop())")
351 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
352 (should (= (python-indent-calculate-indentation) 12))
353 (python-tests-look-at "except (IndexError, AttributeError):")
354 (should (eq (car (python-indent-context)) 'after-line))
355 (should (= (python-indent-calculate-indentation) 8))
356 (python-tests-look-at "print (c)")
357 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
358 (should (= (python-indent-calculate-indentation) 12))
359 (python-tests-look-at "finally:")
360 (should (eq (car (python-indent-context)) 'after-line))
361 (should (= (python-indent-calculate-indentation) 8))
362 (python-tests-look-at "print ('nor a, nor b are true')")
363 (should (eq (car (python-indent-context)) 'after-beginning-of-block))
364 (should (= (python-indent-calculate-indentation) 12))))
365
366(ert-deftest python-indent-after-backslash-1 ()
367 "The most common case."
368 (python-tests-with-temp-buffer
369 "
370from foo.bar.baz import something, something_1 \\\\
371 something_2 something_3, \\\\
372 something_4, something_5
373"
374 (python-tests-look-at "from foo.bar.baz import something, something_1")
375 (should (eq (car (python-indent-context)) 'after-line))
376 (should (= (python-indent-calculate-indentation) 0))
377 (python-tests-look-at "something_2 something_3,")
378 (should (eq (car (python-indent-context)) 'after-backslash))
379 (should (= (python-indent-calculate-indentation) 4))
380 (python-tests-look-at "something_4, something_5")
381 (should (eq (car (python-indent-context)) 'after-backslash))
382 (should (= (python-indent-calculate-indentation) 4))
383 (goto-char (point-max))
384 (should (eq (car (python-indent-context)) 'after-line))
385 (should (= (python-indent-calculate-indentation) 0))))
386
387(ert-deftest python-indent-after-backslash-2 ()
388 "A pretty extreme complicated case."
389 (python-tests-with-temp-buffer
390 "
391objects = Thing.objects.all() \\\\
392 .filter(
393 type='toy',
394 status='bought'
395 ) \\\\
396 .aggregate(
397 Sum('amount')
398 ) \\\\
399 .values_list()
400"
401 (python-tests-look-at "objects = Thing.objects.all()")
402 (should (eq (car (python-indent-context)) 'after-line))
403 (should (= (python-indent-calculate-indentation) 0))
404 (python-tests-look-at ".filter(")
405 (should (eq (car (python-indent-context)) 'after-backslash))
406 (should (= (python-indent-calculate-indentation) 23))
407 (python-tests-look-at "type='toy',")
408 (should (eq (car (python-indent-context)) 'inside-paren))
409 (should (= (python-indent-calculate-indentation) 27))
410 (python-tests-look-at "status='bought'")
411 (should (eq (car (python-indent-context)) 'inside-paren))
412 (should (= (python-indent-calculate-indentation) 27))
413 (python-tests-look-at ") \\\\")
414 (should (eq (car (python-indent-context)) 'inside-paren))
415 (should (= (python-indent-calculate-indentation) 23))
416 (python-tests-look-at ".aggregate(")
417 (should (eq (car (python-indent-context)) 'after-backslash))
418 (should (= (python-indent-calculate-indentation) 23))
419 (python-tests-look-at "Sum('amount')")
420 (should (eq (car (python-indent-context)) 'inside-paren))
421 (should (= (python-indent-calculate-indentation) 27))
422 (python-tests-look-at ") \\\\")
423 (should (eq (car (python-indent-context)) 'inside-paren))
424 (should (= (python-indent-calculate-indentation) 23))
425 (python-tests-look-at ".values_list()")
426 (should (eq (car (python-indent-context)) 'after-backslash))
427 (should (= (python-indent-calculate-indentation) 23))
428 (forward-line 1)
429 (should (eq (car (python-indent-context)) 'after-line))
430 (should (= (python-indent-calculate-indentation) 0))))
431
432
433;;; Navigation
434
435(ert-deftest python-nav-beginning-of-defun-1 ()
436 (python-tests-with-temp-buffer
437 "
438def decoratorFunctionWithArguments(arg1, arg2, arg3):
439 '''print decorated function call data to stdout.
440
441 Usage:
442
443 @decoratorFunctionWithArguments('arg1', 'arg2')
444 def func(a, b, c=True):
445 pass
446 '''
447
448 def wwrap(f):
449 print 'Inside wwrap()'
450 def wrapped_f(*args):
451 print 'Inside wrapped_f()'
452 print 'Decorator arguments:', arg1, arg2, arg3
453 f(*args)
454 print 'After f(*args)'
455 return wrapped_f
456 return wwrap
457"
458 (python-tests-look-at "return wrap")
459 (should (= (save-excursion
460 (python-nav-beginning-of-defun)
461 (point))
462 (save-excursion
463 (python-tests-look-at "def wrapped_f(*args):" -1)
464 (beginning-of-line)
465 (point))))
466 (python-tests-look-at "def wrapped_f(*args):" -1)
467 (should (= (save-excursion
468 (python-nav-beginning-of-defun)
469 (point))
470 (save-excursion
471 (python-tests-look-at "def wwrap(f):" -1)
472 (beginning-of-line)
473 (point))))
474 (python-tests-look-at "def wwrap(f):" -1)
475 (should (= (save-excursion
476 (python-nav-beginning-of-defun)
477 (point))
478 (save-excursion
479 (python-tests-look-at "def decoratorFunctionWithArguments" -1)
480 (beginning-of-line)
481 (point))))))
482
483(ert-deftest python-nav-beginning-of-defun-2 ()
484 (python-tests-with-temp-buffer
485 "
486class C(object):
487
488 def m(self):
489 self.c()
490
491 def b():
492 pass
493
494 def a():
495 pass
496
497 def c(self):
498 pass
499"
500 ;; Nested defuns, are handled with care.
501 (python-tests-look-at "def c(self):")
502 (should (= (save-excursion
503 (python-nav-beginning-of-defun)
504 (point))
505 (save-excursion
506 (python-tests-look-at "def m(self):" -1)
507 (beginning-of-line)
508 (point))))
509 ;; Defuns on same levels should be respected.
510 (python-tests-look-at "def a():" -1)
511 (should (= (save-excursion
512 (python-nav-beginning-of-defun)
513 (point))
514 (save-excursion
515 (python-tests-look-at "def b():" -1)
516 (beginning-of-line)
517 (point))))
518 ;; Jump to a top level defun.
519 (python-tests-look-at "def b():" -1)
520 (should (= (save-excursion
521 (python-nav-beginning-of-defun)
522 (point))
523 (save-excursion
524 (python-tests-look-at "def m(self):" -1)
525 (beginning-of-line)
526 (point))))
527 ;; Jump to a top level defun again.
528 (python-tests-look-at "def m(self):" -1)
529 (should (= (save-excursion
530 (python-nav-beginning-of-defun)
531 (point))
532 (save-excursion
533 (python-tests-look-at "class C(object):" -1)
534 (beginning-of-line)
535 (point))))))
536
537(ert-deftest python-nav-end-of-defun-1 ()
538 (python-tests-with-temp-buffer
539 "
540class C(object):
541
542 def m(self):
543 self.c()
544
545 def b():
546 pass
547
548 def a():
549 pass
550
551 def c(self):
552 pass
553"
554 (should (= (save-excursion
555 (python-tests-look-at "class C(object):")
556 (python-nav-end-of-defun)
557 (point))
558 (save-excursion
559 (point-max))))
560 (should (= (save-excursion
561 (python-tests-look-at "def m(self):")
562 (python-nav-end-of-defun)
563 (point))
564 (save-excursion
565 (python-tests-look-at "def c(self):")
566 (forward-line -1)
567 (point))))
568 (should (= (save-excursion
569 (python-tests-look-at "def b():")
570 (python-nav-end-of-defun)
571 (point))
572 (save-excursion
573 (python-tests-look-at "def b():")
574 (forward-line 2)
575 (point))))
576 (should (= (save-excursion
577 (python-tests-look-at "def c(self):")
578 (python-nav-end-of-defun)
579 (point))
580 (save-excursion
581 (point-max))))))
582
583(ert-deftest python-nav-end-of-defun-2 ()
584 (python-tests-with-temp-buffer
585 "
586def decoratorFunctionWithArguments(arg1, arg2, arg3):
587 '''print decorated function call data to stdout.
588
589 Usage:
590
591 @decoratorFunctionWithArguments('arg1', 'arg2')
592 def func(a, b, c=True):
593 pass
594 '''
595
596 def wwrap(f):
597 print 'Inside wwrap()'
598 def wrapped_f(*args):
599 print 'Inside wrapped_f()'
600 print 'Decorator arguments:', arg1, arg2, arg3
601 f(*args)
602 print 'After f(*args)'
603 return wrapped_f
604 return wwrap
605"
606 (should (= (save-excursion
607 (python-tests-look-at "def decoratorFunctionWithArguments")
608 (python-nav-end-of-defun)
609 (point))
610 (save-excursion
611 (point-max))))
612 (should (= (save-excursion
613 (python-tests-look-at "@decoratorFunctionWithArguments")
614 (python-nav-end-of-defun)
615 (point))
616 (save-excursion
617 (point-max))))
618 (should (= (save-excursion
619 (python-tests-look-at "def wwrap(f):")
620 (python-nav-end-of-defun)
621 (point))
622 (save-excursion
623 (python-tests-look-at "return wwrap")
624 (line-beginning-position))))
625 (should (= (save-excursion
626 (python-tests-look-at "def wrapped_f(*args):")
627 (python-nav-end-of-defun)
628 (point))
629 (save-excursion
630 (python-tests-look-at "return wrapped_f")
631 (line-beginning-position))))
632 (should (= (save-excursion
633 (python-tests-look-at "f(*args)")
634 (python-nav-end-of-defun)
635 (point))
636 (save-excursion
637 (python-tests-look-at "return wrapped_f")
638 (line-beginning-position))))))
639
640
641(ert-deftest python-nav-beginning-of-statement-1 ()
642 (python-tests-with-temp-buffer
643 "
644v1 = 123 + \
645 456 + \
646 789
647v2 = (value1,
648 value2,
649
650 value3,
651 value4)
652v3 = ('this is a string'
653
654 'that is continued'
655 'between lines'
656 'within a paren',
657 # this is a comment, yo
658 'continue previous line')
659v4 = '''
660a very long
661string
662'''
663"
664 (python-tests-look-at "v2 =")
665 (python-util-forward-comment -1)
666 (should (= (save-excursion
667 (python-nav-beginning-of-statement)
668 (point))
669 (python-tests-look-at "v1 =" -1 t)))
670 (python-tests-look-at "v3 =")
671 (python-util-forward-comment -1)
672 (should (= (save-excursion
673 (python-nav-beginning-of-statement)
674 (point))
675 (python-tests-look-at "v2 =" -1 t)))
676 (python-tests-look-at "v4 =")
677 (python-util-forward-comment -1)
678 (should (= (save-excursion
679 (python-nav-beginning-of-statement)
680 (point))
681 (python-tests-look-at "v3 =" -1 t)))
682 (goto-char (point-max))
683 (python-util-forward-comment -1)
684 (should (= (save-excursion
685 (python-nav-beginning-of-statement)
686 (point))
687 (python-tests-look-at "v4 =" -1 t)))))
688
689(ert-deftest python-nav-end-of-statement-1 ()
690 (python-tests-with-temp-buffer
691 "
692v1 = 123 + \
693 456 + \
694 789
695v2 = (value1,
696 value2,
697
698 value3,
699 value4)
700v3 = ('this is a string'
701
702 'that is continued'
703 'between lines'
704 'within a paren',
705 # this is a comment, yo
706 'continue previous line')
707v4 = '''
708a very long
709string
710'''
711"
712 (python-tests-look-at "v1 =")
713 (should (= (save-excursion
714 (python-nav-end-of-statement)
715 (point))
716 (save-excursion
717 (python-tests-look-at "789")
718 (line-end-position))))
719 (python-tests-look-at "v2 =")
720 (should (= (save-excursion
721 (python-nav-end-of-statement)
722 (point))
723 (save-excursion
724 (python-tests-look-at "value4)")
725 (line-end-position))))
726 (python-tests-look-at "v3 =")
727 (should (= (save-excursion
728 (python-nav-end-of-statement)
729 (point))
730 (save-excursion
731 (python-tests-look-at
732 "'continue previous line')")
733 (line-end-position))))
734 (python-tests-look-at "v4 =")
735 (should (= (save-excursion
736 (python-nav-end-of-statement)
737 (point))
738 (save-excursion
739 (goto-char (point-max))
740 (python-util-forward-comment -1)
741 (point))))))
742
743(ert-deftest python-nav-forward-statement-1 ()
744 (python-tests-with-temp-buffer
745 "
746v1 = 123 + \
747 456 + \
748 789
749v2 = (value1,
750 value2,
751
752 value3,
753 value4)
754v3 = ('this is a string'
755
756 'that is continued'
757 'between lines'
758 'within a paren',
759 # this is a comment, yo
760 'continue previous line')
761v4 = '''
762a very long
763string
764'''
765"
766 (python-tests-look-at "v1 =")
767 (should (= (save-excursion
768 (python-nav-forward-statement)
769 (point))
770 (python-tests-look-at "v2 =")))
771 (should (= (save-excursion
772 (python-nav-forward-statement)
773 (point))
774 (python-tests-look-at "v3 =")))
775 (should (= (save-excursion
776 (python-nav-forward-statement)
777 (point))
778 (python-tests-look-at "v4 =")))
779 (should (= (save-excursion
780 (python-nav-forward-statement)
781 (point))
782 (point-max)))))
783
784(ert-deftest python-nav-backward-statement-1 ()
785 (python-tests-with-temp-buffer
786 "
787v1 = 123 + \
788 456 + \
789 789
790v2 = (value1,
791 value2,
792
793 value3,
794 value4)
795v3 = ('this is a string'
796
797 'that is continued'
798 'between lines'
799 'within a paren',
800 # this is a comment, yo
801 'continue previous line')
802v4 = '''
803a very long
804string
805'''
806"
807 (goto-char (point-max))
808 (should (= (save-excursion
809 (python-nav-backward-statement)
810 (point))
811 (python-tests-look-at "v4 =" -1)))
812 (should (= (save-excursion
813 (python-nav-backward-statement)
814 (point))
815 (python-tests-look-at "v3 =" -1)))
816 (should (= (save-excursion
817 (python-nav-backward-statement)
818 (point))
819 (python-tests-look-at "v2 =" -1)))
820 (should (= (save-excursion
821 (python-nav-backward-statement)
822 (point))
823 (python-tests-look-at "v1 =" -1)))))
824
825(ert-deftest python-nav-backward-statement-2 ()
826 :expected-result :failed
827 (python-tests-with-temp-buffer
828 "
829v1 = 123 + \
830 456 + \
831 789
832v2 = (value1,
833 value2,
834
835 value3,
836 value4)
837"
838 ;; FIXME: For some reason `python-nav-backward-statement' is moving
839 ;; back two sentences when starting from 'value4)'.
840 (goto-char (point-max))
841 (python-util-forward-comment -1)
842 (should (= (save-excursion
843 (python-nav-backward-statement)
844 (point))
845 (python-tests-look-at "v2 =" -1 t)))))
846
847(ert-deftest python-nav-beginning-of-block-1 ()
848 (python-tests-with-temp-buffer
849 "
850def decoratorFunctionWithArguments(arg1, arg2, arg3):
851 '''print decorated function call data to stdout.
852
853 Usage:
854
855 @decoratorFunctionWithArguments('arg1', 'arg2')
856 def func(a, b, c=True):
857 pass
858 '''
859
860 def wwrap(f):
861 print 'Inside wwrap()'
862 def wrapped_f(*args):
863 print 'Inside wrapped_f()'
864 print 'Decorator arguments:', arg1, arg2, arg3
865 f(*args)
866 print 'After f(*args)'
867 return wrapped_f
868 return wwrap
869"
870 (python-tests-look-at "return wwrap")
871 (should (= (save-excursion
872 (python-nav-beginning-of-block)
873 (point))
874 (python-tests-look-at "def decoratorFunctionWithArguments" -1)))
875 (python-tests-look-at "print 'Inside wwrap()'")
876 (should (= (save-excursion
877 (python-nav-beginning-of-block)
878 (point))
879 (python-tests-look-at "def wwrap(f):" -1)))
880 (python-tests-look-at "print 'After f(*args)'")
881 (end-of-line)
882 (should (= (save-excursion
883 (python-nav-beginning-of-block)
884 (point))
885 (python-tests-look-at "def wrapped_f(*args):" -1)))
886 (python-tests-look-at "return wrapped_f")
887 (should (= (save-excursion
888 (python-nav-beginning-of-block)
889 (point))
890 (python-tests-look-at "def wwrap(f):" -1)))))
891
892(ert-deftest python-nav-end-of-block-1 ()
893 (python-tests-with-temp-buffer
894 "
895def decoratorFunctionWithArguments(arg1, arg2, arg3):
896 '''print decorated function call data to stdout.
897
898 Usage:
899
900 @decoratorFunctionWithArguments('arg1', 'arg2')
901 def func(a, b, c=True):
902 pass
903 '''
904
905 def wwrap(f):
906 print 'Inside wwrap()'
907 def wrapped_f(*args):
908 print 'Inside wrapped_f()'
909 print 'Decorator arguments:', arg1, arg2, arg3
910 f(*args)
911 print 'After f(*args)'
912 return wrapped_f
913 return wwrap
914"
915 (python-tests-look-at "def decoratorFunctionWithArguments")
916 (should (= (save-excursion
917 (python-nav-end-of-block)
918 (point))
919 (save-excursion
920 (goto-char (point-max))
921 (python-util-forward-comment -1)
922 (point))))
923 (python-tests-look-at "def wwrap(f):")
924 (should (= (save-excursion
925 (python-nav-end-of-block)
926 (point))
927 (save-excursion
928 (python-tests-look-at "return wrapped_f")
929 (line-end-position))))
930 (end-of-line)
931 (should (= (save-excursion
932 (python-nav-end-of-block)
933 (point))
934 (save-excursion
935 (python-tests-look-at "return wrapped_f")
936 (line-end-position))))
937 (python-tests-look-at "f(*args)")
938 (should (= (save-excursion
939 (python-nav-end-of-block)
940 (point))
941 (save-excursion
942 (python-tests-look-at "print 'After f(*args)'")
943 (line-end-position))))))
944
945(ert-deftest python-nav-forward-block-1 ()
946 "This also accounts as a test for `python-nav-backward-block'."
947 (python-tests-with-temp-buffer
948 "
949if request.user.is_authenticated():
950 # def block():
951 # pass
952 try:
953 profile = request.user.get_profile()
954 except Profile.DoesNotExist:
955 profile = Profile.objects.create(user=request.user)
956 else:
957 if profile.stats:
958 profile.recalculate_stats()
959 else:
960 profile.clear_stats()
961 finally:
962 profile.views += 1
963 profile.save()
964"
965 (should (= (save-excursion (python-nav-forward-block))
966 (python-tests-look-at "if request.user.is_authenticated():")))
967 (should (= (save-excursion (python-nav-forward-block))
968 (python-tests-look-at "try:")))
969 (should (= (save-excursion (python-nav-forward-block))
970 (python-tests-look-at "except Profile.DoesNotExist:")))
971 (should (= (save-excursion (python-nav-forward-block))
972 (python-tests-look-at "else:")))
973 (should (= (save-excursion (python-nav-forward-block))
974 (python-tests-look-at "if profile.stats:")))
975 (should (= (save-excursion (python-nav-forward-block))
976 (python-tests-look-at "else:")))
977 (should (= (save-excursion (python-nav-forward-block))
978 (python-tests-look-at "finally:")))
979 ;; When point is at the last block, leave it there and return nil
980 (should (not (save-excursion (python-nav-forward-block))))
981 ;; Move backwards, and even if the number of moves is less than the
982 ;; provided argument return the point.
983 (should (= (save-excursion (python-nav-forward-block -10))
984 (python-tests-look-at
985 "if request.user.is_authenticated():" -1)))))
986
987(ert-deftest python-nav-lisp-forward-sexp-safe-1 ()
988 (python-tests-with-temp-buffer
989 "
990profile = Profile.objects.create(user=request.user)
991profile.notify()
992"
993 (python-tests-look-at "profile =")
994 (python-nav-lisp-forward-sexp-safe 4)
995 (should (looking-at "(user=request.user)"))
996 (python-tests-look-at "user=request.user")
997 (python-nav-lisp-forward-sexp-safe -1)
998 (should (looking-at "(user=request.user)"))
999 (python-nav-lisp-forward-sexp-safe -4)
1000 (should (looking-at "profile ="))
1001 (python-tests-look-at "user=request.user")
1002 (python-nav-lisp-forward-sexp-safe 3)
1003 (should (looking-at ")"))
1004 (python-nav-lisp-forward-sexp-safe 1)
1005 (should (looking-at "$"))
1006 (python-nav-lisp-forward-sexp-safe 1)
1007 (should (looking-at ".notify()"))))
1008
1009(ert-deftest python-nav-forward-sexp-1 ()
1010 (python-tests-with-temp-buffer
1011 "
1012a()
1013b()
1014c()
1015"
1016 (python-tests-look-at "a()")
1017 (python-nav-forward-sexp)
1018 (should (looking-at "$"))
1019 (should (save-excursion
1020 (beginning-of-line)
1021 (looking-at "a()")))
1022 (python-nav-forward-sexp)
1023 (should (looking-at "$"))
1024 (should (save-excursion
1025 (beginning-of-line)
1026 (looking-at "b()")))
1027 (python-nav-forward-sexp)
1028 (should (looking-at "$"))
1029 (should (save-excursion
1030 (beginning-of-line)
1031 (looking-at "c()")))
1032 ;; Movement next to a paren should do what lisp does and
1033 ;; unfortunately It can't change, because otherwise
1034 ;; `blink-matching-open' breaks.
1035 (python-nav-forward-sexp -1)
1036 (should (looking-at "()"))
1037 (should (save-excursion
1038 (beginning-of-line)
1039 (looking-at "c()")))
1040 (python-nav-forward-sexp -1)
1041 (should (looking-at "c()"))
1042 (python-nav-forward-sexp -1)
1043 (should (looking-at "b()"))
1044 (python-nav-forward-sexp -1)
1045 (should (looking-at "a()"))))
1046
1047(ert-deftest python-nav-forward-sexp-2 ()
1048 (python-tests-with-temp-buffer
1049 "
1050def func():
1051 if True:
1052 aaa = bbb
1053 ccc = ddd
1054 eee = fff
1055 return ggg
1056"
1057 (python-tests-look-at "aa =")
1058 (python-nav-forward-sexp)
1059 (should (looking-at " = bbb"))
1060 (python-nav-forward-sexp)
1061 (should (looking-at "$"))
1062 (should (save-excursion
1063 (back-to-indentation)
1064 (looking-at "aaa = bbb")))
1065 (python-nav-forward-sexp)
1066 (should (looking-at "$"))
1067 (should (save-excursion
1068 (back-to-indentation)
1069 (looking-at "ccc = ddd")))
1070 (python-nav-forward-sexp)
1071 (should (looking-at "$"))
1072 (should (save-excursion
1073 (back-to-indentation)
1074 (looking-at "eee = fff")))
1075 (python-nav-forward-sexp)
1076 (should (looking-at "$"))
1077 (should (save-excursion
1078 (back-to-indentation)
1079 (looking-at "return ggg")))
1080 (python-nav-forward-sexp -1)
1081 (should (looking-at "def func():"))))
1082
1083(ert-deftest python-nav-forward-sexp-3 ()
1084 (python-tests-with-temp-buffer
1085 "
1086from some_module import some_sub_module
1087from another_module import another_sub_module
1088
1089def another_statement():
1090 pass
1091"
1092 (python-tests-look-at "some_module")
1093 (python-nav-forward-sexp)
1094 (should (looking-at " import"))
1095 (python-nav-forward-sexp)
1096 (should (looking-at " some_sub_module"))
1097 (python-nav-forward-sexp)
1098 (should (looking-at "$"))
1099 (should
1100 (save-excursion
1101 (back-to-indentation)
1102 (looking-at
1103 "from some_module import some_sub_module")))
1104 (python-nav-forward-sexp)
1105 (should (looking-at "$"))
1106 (should
1107 (save-excursion
1108 (back-to-indentation)
1109 (looking-at
1110 "from another_module import another_sub_module")))
1111 (python-nav-forward-sexp)
1112 (should (looking-at "$"))
1113 (should
1114 (save-excursion
1115 (back-to-indentation)
1116 (looking-at
1117 "pass")))
1118 (python-nav-forward-sexp -1)
1119 (should (looking-at "def another_statement():"))
1120 (python-nav-forward-sexp -1)
1121 (should (looking-at "from another_module import another_sub_module"))
1122 (python-nav-forward-sexp -1)
1123 (should (looking-at "from some_module import some_sub_module"))))
1124
1125(ert-deftest python-nav-up-list-1 ()
1126 (python-tests-with-temp-buffer
1127 "
1128def f():
1129 if True:
1130 return [i for i in range(3)]
1131"
1132 (python-tests-look-at "3)]")
1133 (python-nav-up-list)
1134 (should (looking-at "]"))
1135 (python-nav-up-list)
1136 (should (looking-at "$"))))
1137
1138(ert-deftest python-nav-backward-up-list-1 ()
1139 :expected-result :failed
1140 (python-tests-with-temp-buffer
1141 "
1142def f():
1143 if True:
1144 return [i for i in range(3)]
1145"
1146 (python-tests-look-at "3)]")
1147 (python-nav-backward-up-list)
1148 (should (looking-at "(3)\\]"))
1149 (python-nav-backward-up-list)
1150 (should (looking-at
1151 "\\[i for i in range(3)\\]"))
1152 ;; FIXME: Need to move to beginning-of-statement.
1153 (python-nav-backward-up-list)
1154 (should (looking-at
1155 "return \\[i for i in range(3)\\]"))
1156 (python-nav-backward-up-list)
1157 (should (looking-at "if True:"))
1158 (python-nav-backward-up-list)
1159 (should (looking-at "def f():"))))
1160
1161
1162;;; Shell integration
1163
1164
1165;;; Shell completion
1166
1167
1168;;; PDB Track integration
1169
1170
1171;;; Symbol completion
1172
1173
1174;;; Fill paragraph
1175
1176
1177;;; Skeletons
1178
1179
1180;;; FFAP
1181
1182
1183;;; Code check
1184
1185
1186;;; Eldoc
1187
1188
1189;;; Imenu
1190(ert-deftest python-imenu-prev-index-position-1 ()
1191 (require 'imenu)
1192 (python-tests-with-temp-buffer
1193 "
1194def decoratorFunctionWithArguments(arg1, arg2, arg3):
1195 '''print decorated function call data to stdout.
1196
1197 Usage:
1198
1199 @decoratorFunctionWithArguments('arg1', 'arg2')
1200 def func(a, b, c=True):
1201 pass
1202 '''
1203
1204 def wwrap(f):
1205 print 'Inside wwrap()'
1206 def wrapped_f(*args):
1207 print 'Inside wrapped_f()'
1208 print 'Decorator arguments:', arg1, arg2, arg3
1209 f(*args)
1210 print 'After f(*args)'
1211 return wrapped_f
1212 return wwrap
1213
1214def test(): # Some comment
1215 'This is a test function'
1216 print 'test'
1217
1218class C(object):
1219
1220 def m(self):
1221 self.c()
1222
1223 def b():
1224 pass
1225
1226 def a():
1227 pass
1228
1229 def c(self):
1230 pass
1231"
1232 (let ((expected
1233 '(("*Rescan*" . -99)
1234 ("decoratorFunctionWithArguments" . 2)
1235 ("decoratorFunctionWithArguments.wwrap" . 224)
1236 ("decoratorFunctionWithArguments.wwrap.wrapped_f" . 273)
1237 ("test" . 500)
1238 ("C" . 575)
1239 ("C.m" . 593)
1240 ("C.m.b" . 628)
1241 ("C.m.a" . 663)
1242 ("C.c" . 698))))
1243 (mapc
1244 (lambda (elt)
1245 (should (= (cdr (assoc-string (car elt) expected))
1246 (if (markerp (cdr elt))
1247 (marker-position (cdr elt))
1248 (cdr elt)))))
1249 (imenu--make-index-alist)))))
1250
1251
1252;;; Misc helpers
1253
1254(ert-deftest python-info-current-defun-1 ()
1255 (python-tests-with-temp-buffer
1256 "
1257def foo(a, b):
1258"
1259 (forward-line 1)
1260 (should (string= "foo" (python-info-current-defun)))
1261 (should (string= "def foo" (python-info-current-defun t)))
1262 (forward-line 1)
1263 (should (not (python-info-current-defun)))
1264 (indent-for-tab-command)
1265 (should (string= "foo" (python-info-current-defun)))
1266 (should (string= "def foo" (python-info-current-defun t)))))
1267
1268(ert-deftest python-info-current-defun-2 ()
1269 (python-tests-with-temp-buffer
1270 "
1271class C(object):
1272
1273 def m(self):
1274 if True:
1275 return [i for i in range(3)]
1276 else:
1277 return []
1278
1279 def b():
1280 pass
1281
1282 def a():
1283 pass
1284
1285 def c(self):
1286 pass
1287"
1288 (forward-line 1)
1289 (should (string= "C" (python-info-current-defun)))
1290 (should (string= "class C" (python-info-current-defun t)))
1291 (python-tests-look-at "return [i for ")
1292 (should (string= "C.m" (python-info-current-defun)))
1293 (should (string= "def C.m" (python-info-current-defun t)))
1294 (python-tests-look-at "def b():")
1295 (should (string= "C.m.b" (python-info-current-defun)))
1296 (should (string= "def C.m.b" (python-info-current-defun t)))
1297 (forward-line 2)
1298 (indent-for-tab-command)
1299 (python-indent-dedent-line-backspace 1)
1300 (should (string= "C.m" (python-info-current-defun)))
1301 (should (string= "def C.m" (python-info-current-defun t)))
1302 (python-tests-look-at "def c(self):")
1303 (forward-line -1)
1304 (indent-for-tab-command)
1305 (should (string= "C.m.a" (python-info-current-defun)))
1306 (should (string= "def C.m.a" (python-info-current-defun t)))
1307 (python-indent-dedent-line-backspace 1)
1308 (should (string= "C.m" (python-info-current-defun)))
1309 (should (string= "def C.m" (python-info-current-defun t)))
1310 (python-indent-dedent-line-backspace 1)
1311 (should (string= "C" (python-info-current-defun)))
1312 (should (string= "class C" (python-info-current-defun t)))
1313 (python-tests-look-at "def c(self):")
1314 (should (string= "C.c" (python-info-current-defun)))
1315 (should (string= "def C.c" (python-info-current-defun t)))
1316 (python-tests-look-at "pass")
1317 (should (string= "C.c" (python-info-current-defun)))
1318 (should (string= "def C.c" (python-info-current-defun t)))))
1319
1320(ert-deftest python-info-current-defun-3 ()
1321 (python-tests-with-temp-buffer
1322 "
1323def decoratorFunctionWithArguments(arg1, arg2, arg3):
1324 '''print decorated function call data to stdout.
1325
1326 Usage:
1327
1328 @decoratorFunctionWithArguments('arg1', 'arg2')
1329 def func(a, b, c=True):
1330 pass
1331 '''
1332
1333 def wwrap(f):
1334 print 'Inside wwrap()'
1335 def wrapped_f(*args):
1336 print 'Inside wrapped_f()'
1337 print 'Decorator arguments:', arg1, arg2, arg3
1338 f(*args)
1339 print 'After f(*args)'
1340 return wrapped_f
1341 return wwrap
1342"
1343 (python-tests-look-at "def wwrap(f):")
1344 (forward-line -1)
1345 (should (not (python-info-current-defun)))
1346 (indent-for-tab-command 1)
1347 (should (string= (python-info-current-defun)
1348 "decoratorFunctionWithArguments"))
1349 (should (string= (python-info-current-defun t)
1350 "def decoratorFunctionWithArguments"))
1351 (python-tests-look-at "def wrapped_f(*args):")
1352 (should (string= (python-info-current-defun)
1353 "decoratorFunctionWithArguments.wwrap.wrapped_f"))
1354 (should (string= (python-info-current-defun t)
1355 "def decoratorFunctionWithArguments.wwrap.wrapped_f"))
1356 (python-tests-look-at "return wrapped_f")
1357 (should (string= (python-info-current-defun)
1358 "decoratorFunctionWithArguments.wwrap"))
1359 (should (string= (python-info-current-defun t)
1360 "def decoratorFunctionWithArguments.wwrap"))
1361 (end-of-line 1)
1362 (python-tests-look-at "return wwrap")
1363 (should (string= (python-info-current-defun)
1364 "decoratorFunctionWithArguments"))
1365 (should (string= (python-info-current-defun t)
1366 "def decoratorFunctionWithArguments"))))
1367
1368(ert-deftest python-info-current-symbol-1 ()
1369 (python-tests-with-temp-buffer
1370 "
1371class C(object):
1372
1373 def m(self):
1374 self.c()
1375
1376 def c(self):
1377 print ('a')
1378"
1379 (python-tests-look-at "self.c()")
1380 (should (string= "self.c" (python-info-current-symbol)))
1381 (should (string= "C.c" (python-info-current-symbol t)))))
1382
1383(ert-deftest python-info-current-symbol-2 ()
1384 (python-tests-with-temp-buffer
1385 "
1386class C(object):
1387
1388 class M(object):
1389
1390 def a(self):
1391 self.c()
1392
1393 def c(self):
1394 pass
1395"
1396 (python-tests-look-at "self.c()")
1397 (should (string= "self.c" (python-info-current-symbol)))
1398 (should (string= "C.M.c" (python-info-current-symbol t)))))
1399
1400(ert-deftest python-info-current-symbol-3 ()
1401 "Keywords should not be considered symbols."
1402 :expected-result :failed
1403 (python-tests-with-temp-buffer
1404 "
1405class C(object):
1406 pass
1407"
1408 ;; FIXME: keywords are not symbols.
1409 (python-tests-look-at "class C")
1410 (should (not (python-info-current-symbol)))
1411 (should (not (python-info-current-symbol t)))
1412 (python-tests-look-at "C(object)")
1413 (should (string= "C" (python-info-current-symbol)))
1414 (should (string= "class C" (python-info-current-symbol t)))))
1415
1416(ert-deftest python-info-statement-starts-block-p-1 ()
1417 (python-tests-with-temp-buffer
1418 "
1419def long_function_name(
1420 var_one, var_two, var_three,
1421 var_four):
1422 print (var_one)
1423"
1424 (python-tests-look-at "def long_function_name")
1425 (should (python-info-statement-starts-block-p))
1426 (python-tests-look-at "print (var_one)")
1427 (python-util-forward-comment -1)
1428 (should (python-info-statement-starts-block-p))))
1429
1430(ert-deftest python-info-statement-starts-block-p-2 ()
1431 (python-tests-with-temp-buffer
1432 "
1433if width == 0 and height == 0 and \\\\
1434 color == 'red' and emphasis == 'strong' or \\\\
1435 highlight > 100:
1436 raise ValueError('sorry, you lose')
1437"
1438 (python-tests-look-at "if width == 0 and")
1439 (should (python-info-statement-starts-block-p))
1440 (python-tests-look-at "raise ValueError(")
1441 (python-util-forward-comment -1)
1442 (should (python-info-statement-starts-block-p))))
1443
1444(ert-deftest python-info-statement-ends-block-p-1 ()
1445 (python-tests-with-temp-buffer
1446 "
1447def long_function_name(
1448 var_one, var_two, var_three,
1449 var_four):
1450 print (var_one)
1451"
1452 (python-tests-look-at "print (var_one)")
1453 (should (python-info-statement-ends-block-p))))
1454
1455(ert-deftest python-info-statement-ends-block-p-2 ()
1456 (python-tests-with-temp-buffer
1457 "
1458if width == 0 and height == 0 and \\\\
1459 color == 'red' and emphasis == 'strong' or \\\\
1460 highlight > 100:
1461 raise ValueError(
1462'sorry, you lose'
1463
1464)
1465"
1466 (python-tests-look-at "raise ValueError(")
1467 (should (python-info-statement-ends-block-p))))
1468
1469(ert-deftest python-info-beginning-of-statement-p-1 ()
1470 (python-tests-with-temp-buffer
1471 "
1472def long_function_name(
1473 var_one, var_two, var_three,
1474 var_four):
1475 print (var_one)
1476"
1477 (python-tests-look-at "def long_function_name")
1478 (should (python-info-beginning-of-statement-p))
1479 (forward-char 10)
1480 (should (not (python-info-beginning-of-statement-p)))
1481 (python-tests-look-at "print (var_one)")
1482 (should (python-info-beginning-of-statement-p))
1483 (goto-char (line-beginning-position))
1484 (should (not (python-info-beginning-of-statement-p)))))
1485
1486(ert-deftest python-info-beginning-of-statement-p-2 ()
1487 (python-tests-with-temp-buffer
1488 "
1489if width == 0 and height == 0 and \\\\
1490 color == 'red' and emphasis == 'strong' or \\\\
1491 highlight > 100:
1492 raise ValueError(
1493'sorry, you lose'
1494
1495)
1496"
1497 (python-tests-look-at "if width == 0 and")
1498 (should (python-info-beginning-of-statement-p))
1499 (forward-char 10)
1500 (should (not (python-info-beginning-of-statement-p)))
1501 (python-tests-look-at "raise ValueError(")
1502 (should (python-info-beginning-of-statement-p))
1503 (goto-char (line-beginning-position))
1504 (should (not (python-info-beginning-of-statement-p)))))
1505
1506(ert-deftest python-info-end-of-statement-p-1 ()
1507 (python-tests-with-temp-buffer
1508 "
1509def long_function_name(
1510 var_one, var_two, var_three,
1511 var_four):
1512 print (var_one)
1513"
1514 (python-tests-look-at "def long_function_name")
1515 (should (not (python-info-end-of-statement-p)))
1516 (end-of-line)
1517 (should (not (python-info-end-of-statement-p)))
1518 (python-tests-look-at "print (var_one)")
1519 (python-util-forward-comment -1)
1520 (should (python-info-end-of-statement-p))
1521 (python-tests-look-at "print (var_one)")
1522 (should (not (python-info-end-of-statement-p)))
1523 (end-of-line)
1524 (should (python-info-end-of-statement-p))))
1525
1526(ert-deftest python-info-end-of-statement-p-2 ()
1527 (python-tests-with-temp-buffer
1528 "
1529if width == 0 and height == 0 and \\\\
1530 color == 'red' and emphasis == 'strong' or \\\\
1531 highlight > 100:
1532 raise ValueError(
1533'sorry, you lose'
1534
1535)
1536"
1537 (python-tests-look-at "if width == 0 and")
1538 (should (not (python-info-end-of-statement-p)))
1539 (end-of-line)
1540 (should (not (python-info-end-of-statement-p)))
1541 (python-tests-look-at "raise ValueError(")
1542 (python-util-forward-comment -1)
1543 (should (python-info-end-of-statement-p))
1544 (python-tests-look-at "raise ValueError(")
1545 (should (not (python-info-end-of-statement-p)))
1546 (end-of-line)
1547 (should (not (python-info-end-of-statement-p)))
1548 (goto-char (point-max))
1549 (python-util-forward-comment -1)
1550 (should (python-info-end-of-statement-p))))
1551
1552(ert-deftest python-info-beginning-of-block-p-1 ()
1553 (python-tests-with-temp-buffer
1554 "
1555def long_function_name(
1556 var_one, var_two, var_three,
1557 var_four):
1558 print (var_one)
1559"
1560 (python-tests-look-at "def long_function_name")
1561 (should (python-info-beginning-of-block-p))
1562 (python-tests-look-at "var_one, var_two, var_three,")
1563 (should (not (python-info-beginning-of-block-p)))
1564 (python-tests-look-at "print (var_one)")
1565 (should (not (python-info-beginning-of-block-p)))))
1566
1567(ert-deftest python-info-beginning-of-block-p-2 ()
1568 (python-tests-with-temp-buffer
1569 "
1570if width == 0 and height == 0 and \\\\
1571 color == 'red' and emphasis == 'strong' or \\\\
1572 highlight > 100:
1573 raise ValueError(
1574'sorry, you lose'
1575
1576)
1577"
1578 (python-tests-look-at "if width == 0 and")
1579 (should (python-info-beginning-of-block-p))
1580 (python-tests-look-at "color == 'red' and emphasis")
1581 (should (not (python-info-beginning-of-block-p)))
1582 (python-tests-look-at "raise ValueError(")
1583 (should (not (python-info-beginning-of-block-p)))))
1584
1585(ert-deftest python-info-end-of-block-p-1 ()
1586 (python-tests-with-temp-buffer
1587 "
1588def long_function_name(
1589 var_one, var_two, var_three,
1590 var_four):
1591 print (var_one)
1592"
1593 (python-tests-look-at "def long_function_name")
1594 (should (not (python-info-end-of-block-p)))
1595 (python-tests-look-at "var_one, var_two, var_three,")
1596 (should (not (python-info-end-of-block-p)))
1597 (python-tests-look-at "var_four):")
1598 (end-of-line)
1599 (should (not (python-info-end-of-block-p)))
1600 (python-tests-look-at "print (var_one)")
1601 (should (not (python-info-end-of-block-p)))
1602 (end-of-line 1)
1603 (should (python-info-end-of-block-p))))
1604
1605(ert-deftest python-info-end-of-block-p-2 ()
1606 (python-tests-with-temp-buffer
1607 "
1608if width == 0 and height == 0 and \\\\
1609 color == 'red' and emphasis == 'strong' or \\\\
1610 highlight > 100:
1611 raise ValueError(
1612'sorry, you lose'
1613
1614)
1615"
1616 (python-tests-look-at "if width == 0 and")
1617 (should (not (python-info-end-of-block-p)))
1618 (python-tests-look-at "color == 'red' and emphasis == 'strong' or")
1619 (should (not (python-info-end-of-block-p)))
1620 (python-tests-look-at "highlight > 100:")
1621 (end-of-line)
1622 (should (not (python-info-end-of-block-p)))
1623 (python-tests-look-at "raise ValueError(")
1624 (should (not (python-info-end-of-block-p)))
1625 (end-of-line 1)
1626 (should (not (python-info-end-of-block-p)))
1627 (goto-char (point-max))
1628 (python-util-forward-comment -1)
1629 (should (python-info-end-of-block-p))))
1630
1631(ert-deftest python-info-closing-block-1 ()
1632 (python-tests-with-temp-buffer
1633 "
1634if request.user.is_authenticated():
1635 try:
1636 profile = request.user.get_profile()
1637 except Profile.DoesNotExist:
1638 profile = Profile.objects.create(user=request.user)
1639 else:
1640 if profile.stats:
1641 profile.recalculate_stats()
1642 else:
1643 profile.clear_stats()
1644 finally:
1645 profile.views += 1
1646 profile.save()
1647"
1648 (python-tests-look-at "try:")
1649 (should (not (python-info-closing-block)))
1650 (python-tests-look-at "except Profile.DoesNotExist:")
1651 (should (= (python-tests-look-at "try:" -1 t)
1652 (python-info-closing-block)))
1653 (python-tests-look-at "else:")
1654 (should (= (python-tests-look-at "except Profile.DoesNotExist:" -1 t)
1655 (python-info-closing-block)))
1656 (python-tests-look-at "if profile.stats:")
1657 (should (not (python-info-closing-block)))
1658 (python-tests-look-at "else:")
1659 (should (= (python-tests-look-at "if profile.stats:" -1 t)
1660 (python-info-closing-block)))
1661 (python-tests-look-at "finally:")
1662 (should (= (python-tests-look-at "else:" -2 t)
1663 (python-info-closing-block)))))
1664
1665(ert-deftest python-info-closing-block-2 ()
1666 (python-tests-with-temp-buffer
1667 "
1668if request.user.is_authenticated():
1669 profile = Profile.objects.get_or_create(user=request.user)
1670 if profile.stats:
1671 profile.recalculate_stats()
1672
1673data = {
1674 'else': 'do it'
1675}
1676 'else'
1677"
1678 (python-tests-look-at "'else': 'do it'")
1679 (should (not (python-info-closing-block)))
1680 (python-tests-look-at "'else'")
1681 (should (not (python-info-closing-block)))))
1682
1683(ert-deftest python-info-line-ends-backslash-p-1 ()
1684 (python-tests-with-temp-buffer
1685 "
1686objects = Thing.objects.all() \\\\
1687 .filter(
1688 type='toy',
1689 status='bought'
1690 ) \\\\
1691 .aggregate(
1692 Sum('amount')
1693 ) \\\\
1694 .values_list()
1695"
1696 (should (python-info-line-ends-backslash-p 2)) ; .filter(...
1697 (should (python-info-line-ends-backslash-p 3))
1698 (should (python-info-line-ends-backslash-p 4))
1699 (should (python-info-line-ends-backslash-p 5))
1700 (should (python-info-line-ends-backslash-p 6)) ; ) \...
1701 (should (python-info-line-ends-backslash-p 7))
1702 (should (python-info-line-ends-backslash-p 8))
1703 (should (python-info-line-ends-backslash-p 9))
1704 (should (not (python-info-line-ends-backslash-p 10))))) ; .values_list()...
1705
1706(ert-deftest python-info-beginning-of-backslash-1 ()
1707 (python-tests-with-temp-buffer
1708 "
1709objects = Thing.objects.all() \\\\
1710 .filter(
1711 type='toy',
1712 status='bought'
1713 ) \\\\
1714 .aggregate(
1715 Sum('amount')
1716 ) \\\\
1717 .values_list()
1718"
1719 (let ((first 2)
1720 (second (python-tests-look-at ".filter("))
1721 (third (python-tests-look-at ".aggregate(")))
1722 (should (= first (python-info-beginning-of-backslash 2)))
1723 (should (= second (python-info-beginning-of-backslash 3)))
1724 (should (= second (python-info-beginning-of-backslash 4)))
1725 (should (= second (python-info-beginning-of-backslash 5)))
1726 (should (= second (python-info-beginning-of-backslash 6)))
1727 (should (= third (python-info-beginning-of-backslash 7)))
1728 (should (= third (python-info-beginning-of-backslash 8)))
1729 (should (= third (python-info-beginning-of-backslash 9)))
1730 (should (not (python-info-beginning-of-backslash 10))))))
1731
1732(ert-deftest python-info-continuation-line-p-1 ()
1733 (python-tests-with-temp-buffer
1734 "
1735if width == 0 and height == 0 and \\\\
1736 color == 'red' and emphasis == 'strong' or \\\\
1737 highlight > 100:
1738 raise ValueError(
1739'sorry, you lose'
1740
1741)
1742"
1743 (python-tests-look-at "if width == 0 and height == 0 and")
1744 (should (not (python-info-continuation-line-p)))
1745 (python-tests-look-at "color == 'red' and emphasis == 'strong' or")
1746 (should (python-info-continuation-line-p))
1747 (python-tests-look-at "highlight > 100:")
1748 (should (python-info-continuation-line-p))
1749 (python-tests-look-at "raise ValueError(")
1750 (should (not (python-info-continuation-line-p)))
1751 (python-tests-look-at "'sorry, you lose'")
1752 (should (python-info-continuation-line-p))
1753 (forward-line 1)
1754 (should (python-info-continuation-line-p))
1755 (python-tests-look-at ")")
1756 (should (python-info-continuation-line-p))
1757 (forward-line 1)
1758 (should (not (python-info-continuation-line-p)))))
1759
1760(ert-deftest python-info-block-continuation-line-p-1 ()
1761 (python-tests-with-temp-buffer
1762 "
1763if width == 0 and height == 0 and \\\\
1764 color == 'red' and emphasis == 'strong' or \\\\
1765 highlight > 100:
1766 raise ValueError(
1767'sorry, you lose'
1768
1769)
1770"
1771 (python-tests-look-at "if width == 0 and")
1772 (should (not (python-info-block-continuation-line-p)))
1773 (python-tests-look-at "color == 'red' and emphasis == 'strong' or")
1774 (should (= (python-info-block-continuation-line-p)
1775 (python-tests-look-at "if width == 0 and" -1 t)))
1776 (python-tests-look-at "highlight > 100:")
1777 (should (not (python-info-block-continuation-line-p)))))
1778
1779(ert-deftest python-info-block-continuation-line-p-2 ()
1780 (python-tests-with-temp-buffer
1781 "
1782def foo(a,
1783 b,
1784 c):
1785 pass
1786"
1787 (python-tests-look-at "def foo(a,")
1788 (should (not (python-info-block-continuation-line-p)))
1789 (python-tests-look-at "b,")
1790 (should (= (python-info-block-continuation-line-p)
1791 (python-tests-look-at "def foo(a," -1 t)))
1792 (python-tests-look-at "c):")
1793 (should (not (python-info-block-continuation-line-p)))))
1794
1795(ert-deftest python-info-assignment-continuation-line-p-1 ()
1796 (python-tests-with-temp-buffer
1797 "
1798data = foo(), bar() \\\\
1799 baz(), 4 \\\\
1800 5, 6
1801"
1802 (python-tests-look-at "data = foo(), bar()")
1803 (should (not (python-info-assignment-continuation-line-p)))
1804 (python-tests-look-at "baz(), 4")
1805 (should (= (python-info-assignment-continuation-line-p)
1806 (python-tests-look-at "foo()," -1 t)))
1807 (python-tests-look-at "5, 6")
1808 (should (not (python-info-assignment-continuation-line-p)))))
1809
1810(ert-deftest python-info-assignment-continuation-line-p-2 ()
1811 (python-tests-with-temp-buffer
1812 "
1813data = (foo(), bar()
1814 baz(), 4
1815 5, 6)
1816"
1817 (python-tests-look-at "data = (foo(), bar()")
1818 (should (not (python-info-assignment-continuation-line-p)))
1819 (python-tests-look-at "baz(), 4")
1820 (should (= (python-info-assignment-continuation-line-p)
1821 (python-tests-look-at "(foo()," -1 t)))
1822 (python-tests-look-at "5, 6)")
1823 (should (not (python-info-assignment-continuation-line-p)))))
1824
1825(ert-deftest python-info-looking-at-beginning-of-defun-1 ()
1826 (python-tests-with-temp-buffer
1827 "
1828def decorat0r(deff):
1829 '''decorates stuff.
1830
1831 @decorat0r
1832 def foo(arg):
1833 ...
1834 '''
1835 def wrap():
1836 deff()
1837 return wwrap
1838"
1839 (python-tests-look-at "def decorat0r(deff):")
1840 (should (python-info-looking-at-beginning-of-defun))
1841 (python-tests-look-at "def foo(arg):")
1842 (should (not (python-info-looking-at-beginning-of-defun)))
1843 (python-tests-look-at "def wrap():")
1844 (should (python-info-looking-at-beginning-of-defun))
1845 (python-tests-look-at "deff()")
1846 (should (not (python-info-looking-at-beginning-of-defun)))))
1847
1848(ert-deftest python-info-current-line-comment-p-1 ()
1849 (python-tests-with-temp-buffer
1850 "
1851# this is a comment
1852foo = True # another comment
1853'#this is a string'
1854if foo:
1855 # more comments
1856 print ('bar') # print bar
1857"
1858 (python-tests-look-at "# this is a comment")
1859 (should (python-info-current-line-comment-p))
1860 (python-tests-look-at "foo = True # another comment")
1861 (should (not (python-info-current-line-comment-p)))
1862 (python-tests-look-at "'#this is a string'")
1863 (should (not (python-info-current-line-comment-p)))
1864 (python-tests-look-at "# more comments")
1865 (should (python-info-current-line-comment-p))
1866 (python-tests-look-at "print ('bar') # print bar")
1867 (should (not (python-info-current-line-comment-p)))))
1868
1869(ert-deftest python-info-current-line-empty-p ()
1870 (python-tests-with-temp-buffer
1871 "
1872# this is a comment
1873
1874foo = True # another comment
1875"
1876 (should (python-info-current-line-empty-p))
1877 (python-tests-look-at "# this is a comment")
1878 (should (not (python-info-current-line-empty-p)))
1879 (forward-line 1)
1880 (should (python-info-current-line-empty-p))))
1881
1882
1883;;; Utility functions
1884
1885(ert-deftest python-util-goto-line-1 ()
1886 (python-tests-with-temp-buffer
1887 (concat
1888 "# a comment
1889# another comment
1890def foo(a, b, c):
1891 pass" (make-string 20 ?\n))
1892 (python-util-goto-line 10)
1893 (should (= (line-number-at-pos) 10))
1894 (python-util-goto-line 20)
1895 (should (= (line-number-at-pos) 20))))
1896
1897(ert-deftest python-util-clone-local-variables-1 ()
1898 (let ((buffer (generate-new-buffer
1899 "python-util-clone-local-variables-1"))
1900 (varcons
1901 '((python-fill-docstring-style . django)
1902 (python-shell-interpreter . "python")
1903 (python-shell-interpreter-args . "manage.py shell")
1904 (python-shell-prompt-regexp . "In \\[[0-9]+\\]: ")
1905 (python-shell-prompt-output-regexp . "Out\\[[0-9]+\\]: ")
1906 (python-shell-extra-pythonpaths "/home/user/pylib/")
1907 (python-shell-completion-setup-code
1908 . "from IPython.core.completerlib import module_completion")
1909 (python-shell-completion-module-string-code
1910 . "';'.join(module_completion('''%s'''))\n")
1911 (python-shell-completion-string-code
1912 . "';'.join(get_ipython().Completer.all_completions('''%s'''))\n")
1913 (python-shell-virtualenv-path
1914 . "/home/user/.virtualenvs/project"))))
1915 (with-current-buffer buffer
1916 (kill-all-local-variables)
1917 (dolist (ccons varcons)
1918 (set (make-local-variable (car ccons)) (cdr ccons))))
1919 (python-tests-with-temp-buffer
1920 ""
1921 (python-util-clone-local-variables buffer)
1922 (dolist (ccons varcons)
1923 (should
1924 (equal (symbol-value (car ccons)) (cdr ccons)))))
1925 (kill-buffer buffer)))
1926
1927(ert-deftest python-util-forward-comment-1 ()
1928 (python-tests-with-temp-buffer
1929 (concat
1930 "# a comment
1931# another comment
1932 # bad indented comment
1933# more comments" (make-string 9999 ?\n))
1934 (python-util-forward-comment 1)
1935 (should (= (point) (point-max)))
1936 (python-util-forward-comment -1)
1937 (should (= (point) (point-min)))))
1938
1939
1940(provide 'python-tests)
1941
1942;; Local Variables:
1943;; coding: utf-8
1944;; indent-tabs-mode: nil
1945;; End:
1946
1947;;; python-tests.el ends here