From f4e5b75b47ba40fe4a9848d5d2cc09559de9039c Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sat, 23 Nov 2019 17:44:58 +0100 Subject: [PATCH 1/5] org-manual: Fix `org-latex-subtitle-format' documentation * doc/org-manual.org (LaTeX specific export settings): Fix `org-latex-subtitle-format' documentation. --- doc/org-manual.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/org-manual.org b/doc/org-manual.org index cec7e176b..6476126f8 100644 --- a/doc/org-manual.org +++ b/doc/org-manual.org @@ -13166,7 +13166,7 @@ general options (see [[*Export Settings]]). #+vindex: org-latex-subtitle-format The document's subtitle. It is typeset as per ~org-latex-subtitle-format~. If ~org-latex-subtitle-separate~ is - non-~nil~, it is typed as part of the ~\title~ macro. See + non-~nil~, it is typed outside of the ~\title~ macro. See ~org-latex-hyperref-template~ for customizing metadata items. See ~org-latex-title-command~ for typesetting description into the document's front matter. From 0e70e2a42b1e171f6b2b0f9a95780e62ecd2b0ff Mon Sep 17 00:00:00 2001 From: Sebastian Miele Date: Sun, 20 Oct 2019 21:34:02 +0000 Subject: [PATCH 2/5] ob-core: Respect COMMENTed headlines when expanding noweb references * lisp/ob-core.el (org-babel-expand-noweb-references): Add calls to org-in-commented-heading-p where appropriate. --- lisp/ob-core.el | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lisp/ob-core.el b/lisp/ob-core.el index b1b071dc4..f877ff51b 100644 --- a/lisp/ob-core.el +++ b/lisp/ob-core.el @@ -59,6 +59,7 @@ (declare-function org-element-type "org-element" (element)) (declare-function org-entry-get "org" (pom property &optional inherit literal-nil)) (declare-function org-escape-code-in-region "org-src" (beg end)) +(declare-function org-in-commented-heading-p "org" (&optional no-inheritance)) (declare-function org-indent-line "org" ()) (declare-function org-list-get-list-end "org-list" (item struct prevs)) (declare-function org-list-prevs-alist "org-list" (struct)) @@ -2780,7 +2781,8 @@ block but are passed literally to the \"example-block\"." (concat (funcall c-wrap (car cs)) "\n" b "\n" (funcall c-wrap (cadr cs))))))))) - (if (re-search-forward name-regexp nil t) + (if (and (re-search-forward name-regexp nil t) + (not (org-in-commented-heading-p))) ;; Found a source block named SOURCE-NAME. ;; Assume it is unique; do not look after ;; `:noweb-ref' header argument. @@ -2791,14 +2793,16 @@ block but are passed literally to the \"example-block\"." ;; those with a matching Noweb reference. (let ((expansion nil)) (org-babel-map-src-blocks nil - (let* ((info (org-babel-get-src-block-info 'light)) - (parameters (nth 2 info))) - (when (equal source-name - (cdr (assq :noweb-ref parameters))) - (push (funcall expand-body info) expansion) - (push (or (cdr (assq :noweb-sep parameters)) - "\n") - expansion)))) + (unless (org-in-commented-heading-p) + (let* ((info + (org-babel-get-src-block-info 'light)) + (parameters (nth 2 info))) + (when (equal source-name + (cdr (assq :noweb-ref parameters))) + (push (funcall expand-body info) expansion) + (push (or (cdr (assq :noweb-sep parameters)) + "\n") + expansion))))) (when expansion (mapconcat #'identity (nreverse (cdr expansion)) From 787fa238a9b9e7d8934b08a31174f915b0a0b7c0 Mon Sep 17 00:00:00 2001 From: Sebastian Miele Date: Sun, 20 Oct 2019 21:38:03 +0000 Subject: [PATCH 3/5] Add tests about omission of commented src blocks when e.g. tangling * testing/lisp/test-ob.el (test-ob/noweb-expansion): Add clause to test. * testing/lisp/test-ob-tangle.el (ob-tangle/commented-src-blocks): Add test. --- testing/lisp/test-ob-tangle.el | 84 ++++++++++++++++++++++++++++++++++ testing/lisp/test-ob.el | 24 ++++++++++ 2 files changed, 108 insertions(+) diff --git a/testing/lisp/test-ob-tangle.el b/testing/lisp/test-ob-tangle.el index 47c31dff5..301f7aff7 100644 --- a/testing/lisp/test-ob-tangle.el +++ b/testing/lisp/test-ob-tangle.el @@ -296,6 +296,90 @@ another block (org-split-string (buffer-string)))) (delete-file file)))))) +(ert-deftest ob-tangle/commented-src-blocks () + "Test omission of commented src blocks." + (should + (equal '("A") + (let ((file (make-temp-file "org-tangle-"))) + (unwind-protect + (progn + (org-test-with-temp-text-in-file + (format "#+property: header-args :tangle %S +* A + + #+begin_src emacs-lisp + A + #+end_src + +* COMMENT B + + #+begin_src emacs-lisp + B + #+end_src + +* C + + # #+begin_src emacs-lisp + # C + # #+end_src + +* D + + #+begin_comment + #+begin_src emacs-lisp + D + #+end_src + #+end_comment" + file) + (org-babel-tangle)) + (with-temp-buffer + (insert-file-contents file) + (org-split-string (buffer-string)))) + (delete-file file))))) + (should + (equal '("A") + (let ((file (make-temp-file "org-tangle-"))) + (unwind-protect + (progn + (org-test-with-temp-text-in-file + (format "#+property: header-args :tangle %S +* A + + #+begin_src elisp :noweb yes + A + <> + <> + <> + #+end_src + +* COMMENT B + + #+begin_src elisp :noweb-ref B + B + #+end_src + +* C + + # #+begin_src elisp :noweb-ref C + # C + # #+end_src + +* D + + #+begin_comment + #+begin_src elisp :noweb-ref D + D + #+end_src + #+end_comment" + file) + (let (org-babel-noweb-error-all-langs + org-babel-noweb-error-langs) + (org-babel-tangle))) + (with-temp-buffer + (insert-file-contents file) + (org-split-string (buffer-string)))) + (delete-file file)))))) + (provide 'test-ob-tangle) ;;; test-ob-tangle.el ends here diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el index 367c70f83..681f3403e 100644 --- a/testing/lisp/test-ob.el +++ b/testing/lisp/test-ob.el @@ -758,6 +758,30 @@ x #+name: bar #+begin_src emacs-lisp baz +#+end_src" + (org-babel-expand-noweb-references)))) + ;; Respect COMMENT headlines + (should + (equal "C" + (org-test-with-temp-text " +#+begin_src emacs-lisp :noweb yes + <> +#+end_src + +* COMMENT A +#+name: foo +#+begin_src emacs-lisp + A +#+end_src + +* COMMENT B +#+begin_src emacs-lisp :noweb-ref foo + B +#+end_src + +* C +#+begin_src emacs-lisp :noweb-ref foo + C #+end_src" (org-babel-expand-noweb-references))))) From 3d4365ba036437ddcaccf8942aec7e6e929f7715 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sun, 24 Nov 2019 17:27:53 +0100 Subject: [PATCH 4/5] org-clock: Fix locale issues in tests * testing/lisp/test-org-clock.el (test-org-clock/clocktable/step): (test-org-clock/clocktable/extend-today-until): Fix tests failing due to translation mismatch. --- testing/lisp/test-org-clock.el | 423 +++++++++++++++++---------------- 1 file changed, 217 insertions(+), 206 deletions(-) diff --git a/testing/lisp/test-org-clock.el b/testing/lisp/test-org-clock.el index 53a2cffac..b4afe6983 100644 --- a/testing/lisp/test-org-clock.el +++ b/testing/lisp/test-org-clock.el @@ -876,259 +876,270 @@ CLOCK: [2016-12-28 Wed 13:09]--[2016-12-28 Wed 13:09] => 0:00" ;; Regression test: week crossing month boundary before :wstart ;; day-of-week. (should - (equal " -Weekly report starting on: [2017-09-25 Mon] -| Headline | Time | -|--------------+--------| -| *Total time* | *1:00* | -|--------------+--------| -| Foo | 1:00 |" - (org-test-with-temp-text - "* Foo + (string-match-p + " +.*?\\[2017-09-25 .* +.* +.* +|.*?| \\*1:00\\* | +.* +| Foo +| 1:00 +|" + (org-test-with-temp-text + "* Foo CLOCK: [2017-09-30 Sat 12:00]--[2017-09-30 Sat 13:00] => 1:00 CLOCK: [2017-10-01 Sun 11:00]--[2017-10-01 Sun 13:00] => 2:00 CLOCK: [2017-10-02 Mon 11:00]--[2017-10-02 Mon 14:00] => 3:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - ":step week :block 2017-09 :stepskip0 t"))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + ":step week :block 2017-09 :stepskip0 t"))))) (should - (equal " -Weekly report starting on: [2017-10-01 Sun] -| Headline | Time | -|--------------+--------| -| *Total time* | *2:00* | -|--------------+--------| -| Foo | 2:00 | + (string-match-p + " +.*?\\[2017-10-01 .* +.* +.* +|.*?| \\*2:00\\* | +.* +| Foo +| 2:00 | -Weekly report starting on: [2017-10-02 Mon] -| Headline | Time | -|--------------+--------| -| *Total time* | *7:00* | -|--------------+--------| -| Foo | 7:00 | +.*?\\[2017-10-02 .* +.* +.* +|.*?| \\*7:00\\* | +.* +| Foo +| 7:00 +| -Weekly report starting on: [2017-10-09 Mon] -| Headline | Time | -|--------------+--------| -| *Total time* | *5:00* | -|--------------+--------| -| Foo | 5:00 | +.*?\\[2017-10-09 .* +.* +.* +|.*?| \\*5:00\\* | +.* +| Foo +| 5:00 +| " - (org-test-with-temp-text - "* Foo + (org-test-with-temp-text + "* Foo CLOCK: [2017-09-30 Sat 12:00]--[2017-09-30 Sat 13:00] => 1:00 CLOCK: [2017-10-01 Sun 11:00]--[2017-10-01 Sun 13:00] => 2:00 CLOCK: [2017-10-02 Mon 11:00]--[2017-10-02 Mon 14:00] => 3:00 CLOCK: [2017-10-08 Sun 09:00]--[2017-10-08 Sun 13:00] => 4:00 CLOCK: [2017-10-09 Mon 09:00]--[2017-10-09 Mon 14:00] => 5:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - ":step week :block 2017-10 :stepskip0 t"))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + ":step week :block 2017-10 :stepskip0 t"))))) ;; :step day (should - (equal " -Daily report: [2017-10-02 Mon] -| Headline | Time | -|--------------+--------| -| *Total time* | *3:00* | -|--------------+--------| -| Foo | 3:00 | + (string-match-p + " +.*?\\[2017-10-02 .* +.* +.* +|.*?| \\*3:00\\* | +.* +| Foo +| 3:00 +| -Daily report: [2017-10-03 Tue] -| Headline | Time | -|--------------+--------| -| *Total time* | *0:00* | +.*?\\[2017-10-03 .* +.* +.* +|.*?| \\*0:00\\* | -Daily report: [2017-10-04 Wed] -| Headline | Time | -|--------------+--------| -| *Total time* | *0:00* | +.*?\\[2017-10-04 .* +.* +.* +|.*?| \\*0:00\\* | -Daily report: [2017-10-05 Thu] -| Headline | Time | -|--------------+--------| -| *Total time* | *0:00* | +.*?\\[2017-10-05 .* +.* +.* +|.*?| \\*0:00\\* | -Daily report: [2017-10-06 Fri] -| Headline | Time | -|--------------+--------| -| *Total time* | *0:00* | +.*?\\[2017-10-06 .* +.* +.* +|.*?| \\*0:00\\* | -Daily report: [2017-10-07 Sat] -| Headline | Time | -|--------------+--------| -| *Total time* | *0:00* | +.*?\\[2017-10-07 .* +.* +.* +|.*?| \\*0:00\\* | -Daily report: [2017-10-08 Sun] -| Headline | Time | -|--------------+--------| -| *Total time* | *4:00* | -|--------------+--------| -| Foo | 4:00 |" - (org-test-with-temp-text - "* Foo +.*?\\[2017-10-08 .* +.* +.* +|.*?| \\*4:00\\* | +.* +| Foo +| 4:00 +|" + (org-test-with-temp-text + "* Foo CLOCK: [2017-09-30 Sat 12:00]--[2017-09-30 Sat 13:00] => 1:00 CLOCK: [2017-10-01 Sun 11:00]--[2017-10-01 Sun 13:00] => 2:00 CLOCK: [2017-10-02 Mon 11:00]--[2017-10-02 Mon 14:00] => 3:00 CLOCK: [2017-10-08 Sun 09:00]--[2017-10-08 Sun 13:00] => 4:00 CLOCK: [2017-10-09 Mon 09:00]--[2017-10-09 Mon 14:00] => 5:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - ":step day :block 2017-W40"))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + ":step day :block 2017-W40"))))) ;; Regression test: take :tstart and :tend hours into consideration. (should - (equal " -Weekly report starting on: [2017-12-25 Mon] -| Headline | Time | -|--------------+--------| -| *Total time* | *8:00* | -|--------------+--------| -| Foo | 8:00 |" - (org-test-with-temp-text - "* Foo + (string-match-p + " +.*?\\[2017-12-25 .* +.* +.* +|.*?| \\*8:00\\* | +.* +| Foo +| 8:00 +|" + (org-test-with-temp-text + "* Foo CLOCK: [2017-12-27 Wed 08:00]--[2017-12-27 Wed 16:00] => 8:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - (concat ":step week :tstart \"<2017-12-25 Mon>\" " - ":tend \"<2017-12-27 Wed 23:59>\"")))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + (concat ":step week :tstart \"<2017-12-25 Mon>\" " + ":tend \"<2017-12-27 Wed 23:59>\"")))))) (should - (equal " -Daily report: [2017-12-27 Wed] -| Headline | Time | -|--------------+--------| -| *Total time* | *8:00* | -|--------------+--------| -| Foo | 8:00 |" - (org-test-with-temp-text - "* Foo + (string-match-p + " +.*?\\[2017-12-27 .* +.* +.* +|.*?| \\*8:00\\* | +.* +| Foo +| 8:00 +|" + (org-test-with-temp-text + "* Foo CLOCK: [2017-12-27 Wed 08:00]--[2017-12-27 Wed 16:00] => 8:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - (concat ":step day :tstart \"<2017-12-25 Mon>\" " - ":tend \"<2017-12-27 Wed 23:59>\" :stepskip0 t")))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + (concat ":step day :tstart \"<2017-12-25 Mon>\" " + ":tend \"<2017-12-27 Wed 23:59>\" :stepskip0 t")))))) ;; Test :step week", without or with ":wstart" parameter. (should - (equal " -Weekly report starting on: [2012-03-26 Mon] -| Headline | Time | -|--------------+--------| -| *Total time* | *8:00* | -|--------------+--------| -| Foo | 8:00 | + (string-match-p + " +.*?\\[2012-03-26 .* +.* +.* +|.*?| \\*8:00\\* | +.* +| Foo +| 8:00 +| -Weekly report starting on: [2012-04-02 Mon] -| Headline | Time | -|--------------+--------| -| *Total time* | *8:00* | -|--------------+--------| -| Foo | 8:00 | +.*?\\[2012-04-02 .* +.* +.* +|.*?| \\*8:00\\* | +.* +| Foo +| 8:00 +| " - (org-test-with-temp-text - "* Foo + (org-test-with-temp-text + "* Foo CLOCK: [2012-03-29 Thu 08:00]--[2012-03-29 Thu 16:00] => 8:00 CLOCK: [2012-04-03 Thu 08:00]--[2012-04-03 Thu 16:00] => 8:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - ":step week :block 2012 :stepskip0 t"))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + ":step week :block 2012 :stepskip0 t"))))) (should - (equal " -Weekly report starting on: [2012-03-29 Thu] -| Headline | Time | -|--------------+---------| -| *Total time* | *16:00* | -|--------------+---------| -| Foo | 16:00 | + (string-match-p + " +.*?\\[2012-03-29 .* +.* +.* +|.*?| \\*16:00\\* | +.* +| Foo +| 16:00 +| " - (org-test-with-temp-text - "* Foo + (org-test-with-temp-text + "* Foo CLOCK: [2012-03-29 Thu 08:00]--[2012-03-29 Thu 16:00] => 8:00 CLOCK: [2012-04-03 Thu 08:00]--[2012-04-03 Thu 16:00] => 8:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - ":step week :wstart 4 :block 2012 :stepskip0 t"))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + ":step week :wstart 4 :block 2012 :stepskip0 t"))))) ;; Test ":step month" without and with ":mstart". (should - (equal " -Monthly report starting on: [2014-03-01 Sat] -| Headline | Time | -|--------------+--------| -| *Total time* | *8:00* | -|--------------+--------| -| Foo | 8:00 | + (string-match-p + " +.*?\\[2014-03-01 .* +.* +.* +|.*?| \\*8:00\\* | +.* +| Foo +| 8:00 +| -Monthly report starting on: [2014-04-01 Tue] -| Headline | Time | -|--------------+--------| -| *Total time* | *8:00* | -|--------------+--------| -| Foo | 8:00 | +.*?\\[2014-04-01 .* +.* +.* +|.*?| \\*8:00\\* | +.* +| Foo +| 8:00 +| " - (org-test-with-temp-text - "* Foo + (org-test-with-temp-text + "* Foo CLOCK: [2014-03-04 Tue 08:00]--[2014-03-04 Tue 16:00] => 8:00 CLOCK: [2014-04-03 Thu 08:00]--[2014-04-03 Thu 16:00] => 8:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - ":step month :block 2014 :stepskip0 t"))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + ":step month :block 2014 :stepskip0 t"))))) (should - (equal " -Monthly report starting on: [2014-03-04 Tue] -| Headline | Time | -|--------------+---------| -| *Total time* | *16:00* | -|--------------+---------| -| Foo | 16:00 | + (string-match-p + " +.*?\\[2014-03-04 .* +.* +.* +|.*?| \\*16:00\\* | +.* +| Foo +| 16:00 +| " - (org-test-with-temp-text - "* Foo + (org-test-with-temp-text + "* Foo CLOCK: [2014-03-04 Tue 08:00]--[2014-03-04 Tue 16:00] => 8:00 CLOCK: [2014-04-03 Thu 08:00]--[2014-04-03 Thu 16:00] => 8:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - ":step month :mstart 4 :block 2014 :stepskip0 t"))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + ":step month :mstart 4 :block 2014 :stepskip0 t"))))) ;; Test ":step year". (should - (equal " -Annual report starting on: [2012-01-01 Sun] -| Headline | Time | -|--------------+--------| -| *Total time* | *8:00* | -|--------------+--------| -| Foo | 8:00 | + (string-match-p + " +.*?\\[2012-01-01 .* +.* +.* +|.*?| \\*8:00\\* | +.* +| Foo +| 8:00 +| -Annual report starting on: [2014-01-01 Wed] -| Headline | Time | -|--------------+--------| -| *Total time* | *8:00* | -|--------------+--------| -| Foo | 8:00 | +.*?\\[2014-01-01 .* +.* +.* +|.*?| \\*8:00\\* | +.* +| Foo +| 8:00 +| " - (org-test-with-temp-text - "* Foo + (org-test-with-temp-text + "* Foo CLOCK: [2012-03-29 Thu 08:00]--[2012-03-29 Thu 16:00] => 8:00 CLOCK: [2014-03-04 Tue 08:00]--[2014-03-04 Tue 16:00] => 8:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - ":step year :block untilnow :stepskip0 t"))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + ":step year :block untilnow :stepskip0 t"))))) ;; Regression test: Respect DST (should - (equal " -Daily report: [2018-10-29 Mon] -| Headline | Time | -|--------------+--------| -| *Total time* | *8:00* | -|--------------+--------| -| Foo | 8:00 | + (string-match-p + " +.*?\\[2018-10-29 .* +.* +.* +|.*?| \\*8:00\\* | +.* +| Foo +| 8:00 +| " - (org-test-with-temp-text - "* Foo + (org-test-with-temp-text + "* Foo CLOCK: [2018-10-29 Mon 08:00]--[2018-10-29 Mon 16:00] => 8:00" - (let ((system-time-locale "en_US")) - (test-org-clock-clocktable-contents - (concat ":step day " - ":stepskip0 t " - ":tstart \"2018-10-01\" " - ":tend \"2018-11-01\""))))))) + (let ((system-time-locale "en_US")) + (test-org-clock-clocktable-contents + (concat ":step day " + ":stepskip0 t " + ":tstart \"2018-10-01\" " + ":tend \"2018-11-01\""))))))) (ert-deftest test-org-clock/clocktable/extend-today-until () "Test assignment of clock time to days in presence of \"org-extend-today-until\"." @@ -1154,20 +1165,20 @@ CLOCK: [2017-10-01 Sun 11:00]--[2017-10-01 Sun 13:00] => 2:00" ;; Week-length block - time on Monday before 04:00 should be ;; assigned to previous week. (should - (equal " -Weekly report starting on: [2017-10-01 Sun] -| Headline | Time | -|--------------+--------| -| *Total time* | *2:00* | -|--------------+--------| -| Foo | 2:00 | + (string-match-p " +.*? \\[2017-10-01 .* +.* +.* +|.*?| \\*2:00\\* | +.* +| Foo +| 2:00 | -Weekly report starting on: [2017-10-02 Mon] -| Headline | Time | -|--------------+--------| -| *Total time* | *2:00* | -|--------------+--------| -| Foo | 2:00 | +.*? \\[2017-10-02 .* +.* +.* +|.*?| \\*2:00\\* | +.* +| Foo +| 2:00 | " (org-test-with-temp-text "* Foo From be7e88ae30c27e4c7ac0412a5c8675e778680a45 Mon Sep 17 00:00:00 2001 From: Marco Wahl Date: Tue, 26 Nov 2019 22:24:55 +0100 Subject: [PATCH 5/5] agenda: Fix: Don't loop over headlines in region at agenda-todo * lisp/org-agenda.el (org-agenda-todo): Set the respective variable to nil. --- lisp/org-agenda.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el index d389fc253..3df8af620 100644 --- a/lisp/org-agenda.el +++ b/lisp/org-agenda.el @@ -9162,6 +9162,7 @@ the same tree node, and the headline of the tree node in the Org file." (hdmarker (org-get-at-bol 'org-hd-marker)) (todayp (org-agenda-today-p (org-get-at-bol 'day))) (inhibit-read-only t) + org-loop-over-headlines-in-active-region org-agenda-headline-snapshot-before-repeat newhead just-one) (org-with-remote-undo buffer (with-current-buffer buffer