3
3
;; Copyright (C) 1989-1994 Bates, Kademan, Ritter and Smith
4
4
;; Copyright (C) 1997, A.J. Rossini <rossini@stat.sc.edu>
5
5
;; Copyright (C) 1998--2001 A.J. Rossini, Martin Maechler, Kurt Hornik and
6
;; Richard M. Heiberger <rmh@temple.edu>.
6
;; Richard M. Heiberger <rmh@temple.edu>.
7
7
;; Copyright (C) 2001--2010 A.J. Rossini, Rich M. Heiberger, Martin
8
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
8
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
9
9
;; Copyright (C) 2011--2012 A.J. Rossini, Richard M. Heiberger, Martin Maechler,
10
;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu.
13
;; Original Author: David Smith <dsmith@stats.adelaide.edu.au>
10
;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu.
12
;; Author: David Smith <dsmith@stats.adelaide.edu.au>
14
13
;; Created: 7 Jan 1994
15
;; Maintainers: ESS-core <ESS-core@r-project.org>
14
;; Maintainer: ESS-core <ESS-core@r-project.org>
17
16
;; This file is part of ESS
24
23
;; This file is distributed in the hope that it will be useful,
25
24
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
26
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
26
;; GNU General Public License for more details.
29
28
;; You should have received a copy of the GNU General Public License
30
;; along with GNU Emacs; see the file COPYING. If not, write to
29
;; along with GNU Emacs; see the file COPYING. If not, write to
31
30
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
49
(autoload 'ess-eval-region "ess-inf" "[autoload]" t)
50
(autoload 'ess-eval-region-and-go "ess-inf" "[autoload]" t)
51
(autoload 'ess-eval-function "ess-inf" "[autoload]" t)
52
(autoload 'ess-eval-function-and-go "ess-inf" "[autoload]" t)
53
(autoload 'ess-eval-line "ess-inf" "[autoload]" t)
54
(autoload 'ess-eval-line-and-go "ess-inf" "[autoload]" t)
55
(autoload 'ess-eval-line-and-step "ess-inf" "[autoload]" t)
57
(autoload 'ess-beginning-of-function "ess-mode" "[autoload]" t)
58
(autoload 'ess-end-of-function "ess-mode" "[autoload]" t)
60
(autoload 'ess-load-file "ess-inf" "[autoload]" t)
61
(autoload 'ess-command "ess-inf" "(autoload)" nil)
62
(autoload 'ess-display-temp-buffer "ess-inf" "(autoload)" nil)
63
(autoload 'ess-switch-to-ESS "ess-inf" "(autoload)" nil)
48
(autoload 'ess-eval-region "ess-inf" "[autoload]" t)
49
(autoload 'ess-eval-region-and-go "ess-inf" "[autoload]" t)
50
(autoload 'ess-eval-function "ess-inf" "[autoload]" t)
51
(autoload 'ess-eval-function-and-go "ess-inf" "[autoload]" t)
52
(autoload 'ess-eval-line "ess-inf" "[autoload]" t)
53
(autoload 'ess-eval-line-and-go "ess-inf" "[autoload]" t)
54
(autoload 'ess-eval-line-and-step "ess-inf" "[autoload]" t)
56
(autoload 'ess-beginning-of-function "ess-mode" "[autoload]" t)
57
(autoload 'ess-end-of-function "ess-mode" "[autoload]" t)
59
(autoload 'ess-load-file "ess-inf" "[autoload]" t)
60
(autoload 'ess-command "ess-inf" "(autoload)" nil)
61
(autoload 'ess-display-temp-buffer "ess-inf" "(autoload)" nil)
62
(autoload 'ess-switch-to-ESS "ess-inf" "(autoload)" nil)
64
63
(autoload 'ess-read-object-name-default "ess-inf" "(autoload)" nil)
65
(autoload 'ess-make-buffer-current "ess-inf" "(autoload)" nil)
66
(autoload 'ess-search-list "ess-inf" "(autoload)" nil)
67
(autoload 'ess-get-object-list "ess-inf" "(autoload)" nil)
64
(autoload 'ess-make-buffer-current "ess-inf" "(autoload)" nil)
65
(autoload 'ess-search-list "ess-inf" "(autoload)" nil)
66
(autoload 'ess-get-object-list "ess-inf" "(autoload)" nil)
69
(autoload 'ess-ddeclient-p "ess-inf" "(autoload)" nil)
68
(autoload 'ess-ddeclient-p "ess-inf" "(autoload)" nil)
71
70
(autoload 'ess-display-help-on-object-ddeclient "ess-dde" "(autoload)" nil)
88
87
Utility used in \\[ess-display-help-on-object]."
90
89
;; search in first nr-first (default 120) chars only
91
(if (not nr-first) (setq nr-first 120))
90
(if (not nr-first) (setq nr-first 150))
93
92
(let* ((searching nil)
94
(buffer-ok (bufferp buffer))
97
(save-excursion;; ask for new buffer if old one looks bogus ..
100
(ess-write-to-dribble-buffer
101
(format "(ess-help-bogus-buffer-p %s)" (buffer-name))))
93
(buffer-ok (bufferp buffer))
96
(save-excursion;; ask for new buffer if old one looks bogus ..
99
(ess-write-to-dribble-buffer
100
(format "(ess-help-bogus-buffer-p %s)" (buffer-name))))
105
(case-fold-search t) )
106
(or ;; evaluate up to first non-nil (or end):
107
(< (- (point-max) PM) 80); buffer less than 80 chars
108
(not (setq searching t))
109
(progn (goto-char PM) ;; R:
110
(re-search-forward "Error in help" nr-first t))
111
(progn (goto-char PM) ;; S-plus 5.1 :
112
(re-search-forward "^cat: .*--" nr-first t))
113
(progn (goto-char PM) ;; S version 3 ; R :
114
(re-search-forward "no documentation for [^ \t\n]+" nr-first t))
104
(case-fold-search t) )
105
;; todo: move to customize-alist
106
(or ;; evaluate up to first non-nil (or end):
107
(not (setq searching t))
108
(progn (goto-char PM) ;; R:
109
(re-search-forward "Error in help" nr-first t))
110
(progn (goto-char PM) ;; S-plus 5.1 :
111
(re-search-forward "^cat: .*--" nr-first t))
112
(progn (goto-char PM) ;; S version 3 ; R :
113
(re-search-forward "no documentation for [^ \t\n]+" nr-first t))
114
(progn (goto-char PM) ;; stata
115
(re-search-forward "^help for.*not found" nr-first t))
116
(< (- (point-max) PM) 80); buffer less than 80 chars
118
(ess-write-to-dribble-buffer
119
(format " |--> %s [searching %s]\n" res searching)))
120
(ess-write-to-dribble-buffer
121
(format " |--> %s [searching %s]\n" res searching)))
121
123
(if (and res return-match searching)
122
(list (match-beginning 0) (match-end 0))
124
(list (match-beginning 0) (match-end 0))
155
157
(list (ess-find-help-file "Help on")))))
157
159
(if (or (ess-ddeclient-p)
158
(equal inferior-ess-help-filetype "chm"))
160
(equal inferior-ess-help-filetype "chm"))
159
161
(if (ess-ddeclient-p)
160
(ess-display-help-on-object-ddeclient object) ;; ddeclient version
161
(ess-eval-linewise (concat "help(" object ")"))) ;; "chm" version
162
(ess-display-help-on-object-ddeclient object) ;; ddeclient version
163
(ess-eval-linewise (concat "help(" object ")"))) ;; "chm" version
163
165
;; else: "normal", non-DDE behavior:
164
166
(let* ((hb-name (concat "*help["
165
ess-current-process-name
167
(old-hb-p (get-buffer hb-name))
168
(tbuffer (get-buffer-create hb-name))
167
ess-current-process-name
169
(old-hb-p (get-buffer hb-name))
170
(tbuffer (get-buffer-create hb-name))
169
171
;;VS: this curr-* kludge is not needed here,
170
172
;;everything should be set by ess-setq-vars-local latter
171
173
;; (curr-help-sec-regex ess-help-sec-regex)
172
174
;; (curr-help-sec-keys-alist ess-help-sec-keys-alist)
174
(alist ess-local-customize-alist))
176
(alist ess-local-customize-alist))
175
177
(with-current-buffer tbuffer
176
178
(ess-setq-vars-local (eval alist))
177
179
(set-syntax-table ess-mode-syntax-table)
198
200
(goto-char (point-min))))
200
(let ((PM (point-min))
202
(ess-help-bogus-buffer-p (current-buffer) nil 'give-match )))
205
ess-help-kill-bogus-buffers)
207
(if (not (listp nodocs))
208
(setq nodocs (list PM (point-max))))
209
(ess-write-to-dribble-buffer
210
(format "(ess-help: error-buffer '%s' nodocs (%d %d)\n"
211
(buffer-name) (car nodocs) (cadr nodocs)))
212
;; Avoid using 'message here -- may be %'s in string
213
;;(princ (buffer-substring (car nodocs) (cadr nodocs)) t)
214
;; MM [3/2000]: why avoid? Yes, I *do* want message:
215
(message "%s" (buffer-substring (car nodocs) (cadr nodocs)))
216
;; ^^^ fixme : remove new lines from the above {and abbrev.}
218
(kill-buffer tbuffer))
220
;; else : show the help buffer.
222
;; Check if this buffer describes where help can be found in
223
;; various packages. (R only). This is a kind of bogus help
224
;; buffer, but it should not be killed immediately even if
225
;; ess-help-kill-bogus-buffers is t.
227
;; e.g. if within R, the user does:
229
;; > options("help.try.all.packages" = TRUE)
233
;; then a list of packages for where ?rlm is defined is
234
;; shown. (In this case, rlm is in package MASS). This
235
;; help buffer is then renamed *help[R](rlm in packages)* so
236
;; that after MASS is loaded, ?rlm will then show
239
(if (equal inferior-ess-program inferior-R-program-name)
240
;; this code should be used only for R processes.
242
(goto-char (point-min))
243
(if (looking-at "Help for topic")
246
(concat "*help[" ess-current-process-name
247
"](" object " in packages)*")))
248
;; if NEWBUF already exists, remove it.
249
(if (get-buffer newbuf)
250
(kill-buffer newbuf))
251
(rename-buffer newbuf)))))
253
;;dbg (ess-write-to-dribble-buffer
254
;;dbg (format "(ess-help '%s' before switch-to..\n" hb-name)
255
(set-buffer-modified-p 'nil)
256
(toggle-read-only t))))
202
(let ((PM (point-min))
204
(ess-help-bogus-buffer-p (current-buffer) nil 'give-match )))
207
ess-help-kill-bogus-buffers)
209
(if (not (listp nodocs))
210
(setq nodocs (list PM (point-max))))
211
(ess-write-to-dribble-buffer
212
(format "(ess-help: error-buffer '%s' nodocs (%d %d)\n"
213
(buffer-name) (car nodocs) (cadr nodocs)))
214
;; Avoid using 'message here -- may be %'s in string
215
;;(princ (buffer-substring (car nodocs) (cadr nodocs)) t)
216
;; MM [3/2000]: why avoid? Yes, I *do* want message:
217
(message "%s" (buffer-substring (car nodocs) (cadr nodocs)))
218
;; ^^^ fixme : remove new lines from the above {and abbrev.}
220
(kill-buffer tbuffer))
222
;; else : show the help buffer.
224
;; Check if this buffer describes where help can be found in
225
;; various packages. (R only). This is a kind of bogus help
226
;; buffer, but it should not be killed immediately even if
227
;; ess-help-kill-bogus-buffers is t.
229
;; e.g. if within R, the user does:
231
;; > options("help.try.all.packages" = TRUE)
235
;; then a list of packages for where ?rlm is defined is
236
;; shown. (In this case, rlm is in package MASS). This
237
;; help buffer is then renamed *help[R](rlm in packages)* so
238
;; that after MASS is loaded, ?rlm will then show
241
(if (equal inferior-ess-program inferior-R-program-name)
242
;; this code should be used only for R processes.
244
(goto-char (point-min))
245
(if (looking-at "Help for topic")
248
(concat "*help[" ess-current-process-name
249
"](" object " in packages)*")))
250
;; if NEWBUF already exists, remove it.
251
(if (get-buffer newbuf)
252
(kill-buffer newbuf))
253
(rename-buffer newbuf)))))
255
;;dbg (ess-write-to-dribble-buffer
256
;;dbg (format "(ess-help '%s' before switch-to..\n" hb-name)
257
(set-buffer-modified-p 'nil)
258
(toggle-read-only t))))
257
259
(when (buffer-live-p tbuffer)
258
(ess--switch-to-help-buffer tbuffer))
260
(ess--switch-to-help-buffer tbuffer))
508
510
(defvar ess-help-frame nil
509
511
"Stores the frame used for displaying R help buffers.")
511
(defun ess-help-own-frame (buffer &rest ignore)
513
(defun ess-help-own-frame (buffer &rest ignore)
512
514
"Put all ESS help buffers into `ess-help-frame'."
513
515
;; SJE: Code adapted from Kevin Rodgers.
514
516
(if (frame-live-p ess-help-frame)
516
(or (frame-visible-p ess-help-frame)
517
(make-frame-visible ess-help-frame))
518
(raise-frame ess-help-frame)
519
(select-frame ess-help-frame)
520
(switch-to-buffer buffer)
518
(or (frame-visible-p ess-help-frame)
519
(make-frame-visible ess-help-frame))
520
(raise-frame ess-help-frame)
521
(select-frame ess-help-frame)
522
(switch-to-buffer buffer)
523
525
(let ((window (special-display-popup-frame buffer)))
524
526
(set-window-dedicated-p window nil)
592
594
;; One reason for the following menu is to <TEACH> the user about key strokes
593
595
(defvar ess-help-mode-menu
595
["Search Forward" isearch-forward t]
596
["Next Section" ess-skip-to-next-section t]
597
["Previous Section" ess-skip-to-previous-section t]
598
["Help on Section Skipping" ess-describe-sec-map t]
599
["Beginning of Buffer" beginning-of-buffer t]
600
["End of Buffer" end-of-buffer t]
602
["Help on ..." ess-display-help-on-object t]
597
["Search Forward" isearch-forward t]
598
["Next Section" ess-skip-to-next-section t]
599
["Previous Section" ess-skip-to-previous-section t]
600
["Help on Section Skipping" ess-describe-sec-map t]
601
["Beginning of Buffer" beginning-of-buffer t]
602
["End of Buffer" end-of-buffer t]
604
["Help on ..." ess-display-help-on-object t]
603
605
["Index of ..." ess-display-index t]
604
606
["Vignettes" ess-display-vignettes t]
605
607
["Open in Browser" ess-display-help-in-browser t]
607
["Eval Line" ess-eval-line-and-step t]
608
["Eval Paragraph & step" ess-eval-paragraph-and-step t]
609
["Eval Region & Go" ess-eval-region-and-go t]
610
["Switch to ESS Process" ess-switch-to-ESS t]
611
["Switch to End of ESS Proc." ess-switch-to-end-of-ESS t]
612
["Switch _the_ Process" ess-switch-process t]
614
["Describe ESS-help Mode" ess-describe-help-mode t]
616
["Kill Buffer" kill-this-buffer t]
617
["Kill Buffer & Go" ess-kill-buffer-and-go t]
609
["Eval Line" ess-eval-line-and-step t]
610
["Eval Paragraph & step" ess-eval-paragraph-and-step t]
611
["Eval Region & Go" ess-eval-region-and-go t]
612
["Switch to ESS Process" ess-switch-to-ESS t]
613
["Switch to End of ESS Proc." ess-switch-to-end-of-ESS t]
614
["Switch _the_ Process" ess-switch-process t]
616
["Describe ESS-help Mode" ess-describe-help-mode t]
618
["Kill Buffer" kill-this-buffer t]
619
["Kill Buffer & Go" ess-kill-buffer-and-go t]
619
621
"Menu used in ess-help mode.")
622
623
(defun ess-help-mode ()
623
624
;;; Largely ripped from more-mode.el,
624
625
;;; originally by Wolfgang Rupprecht wolfgang@mgm.mit.edu
625
626
"Mode for viewing ESS help files.
626
627
Use SPC and DEL to page back and forth through the file.
627
Use `n' and `p' to move to next and previous section,
628
Use `n' and `p' to move to next and previous section,
628
629
`s' to jump to a particular section; `s ?' for help.
629
630
Use `q' to return to your ESS session; `x' to kill this buffer first.
630
631
The usual commands for evaluating ESS source are available.
662
663
;;*;; User commands defined in ESS help mode
664
665
(defun ess-skip-to-help-section nil
665
"Jump to a section heading of a help buffer. The section selected
666
"Jump to a section heading of a help buffer. The section selected
666
667
is determined by the command letter used to invoke the command, as
667
indicated by `ess-help-sec-keys-alist'. Use \\[ess-describe-sec-map]
668
indicated by `ess-help-sec-keys-alist'. Use \\[ess-describe-sec-map]
668
669
to see which keystrokes find which sections."
670
671
(let ((old-point (point))
671
(case-fold-search nil))
672
(case-fold-search nil))
672
673
(goto-char (point-min))
673
674
(let ((the-sec (cdr (assoc (if (featurep 'xemacs) last-command-char last-command-event)
674
ess-help-sec-keys-alist))))
675
ess-help-sec-keys-alist))))
675
676
(if (not the-sec) (error "Invalid section key: %c"
677
(if (re-search-forward (concat "^" the-sec) nil t) nil
678
(message "No %s section in this help. Sorry." the-sec)
679
(goto-char old-point))))))
678
(if (re-search-forward (concat "^" the-sec) nil t) nil
679
(message "No %s section in this help. Sorry." the-sec)
680
(goto-char old-point))))))
681
682
(defun ess-skip-to-next-section nil
682
683
"Jump to next section in ESS help buffer."
724
725
(insert "\nFull list of key definitions:\n"
725
(substitute-command-keys
726
"\\{ess-help-sec-map}")))))
726
(substitute-command-keys
727
"\\{ess-help-sec-map}")))))
728
(defun ess-helpobjs-at-point (&optional slist)
729
(defun ess-helpobjs-at-point (slist)
729
730
;;; Return a list (def obj fun) where OBJ is a name at point, FUN - name of
730
731
;;; the function call point is in. DEF is either OBJ or FUN (in that order)
731
732
;;; which has a a help file, i.e. it is a member of slist (string-list). nil
734
(setq slist (ess-get-help-topics-list ess-current-process-name)))
735
734
(let ((obj (ess-read-object-name-default))
736
(fun (condition-case ()
739
(narrow-to-region (max (point-min) (- (point) 1000))
743
(ess-read-object-name-default)))
735
(fun (condition-case ()
738
(narrow-to-region (max (point-min) (- (point) 1000))
742
(ess-read-object-name-default)))
745
744
(unless (string-match "[[:alpha:]]" obj) ;;exclude numbers
747
746
(list (or (car (member obj slist))
748
(car (member fun slist)))
747
(car (member fun slist)))
751
750
;; defunct old name:
752
751
(defun ess-read-helpobj-name-default (slist)
756
755
"Find help, prompting for P-STRING. Note that we can't search SAS,
757
756
Stata or XLispStat for additional information."
758
757
(ess-make-buffer-current)
759
(if (string-match "\\(XLS\\)\\|\\(STA\\)\\|\\(SAS\\)" ess-language)
760
(list (read-string p-string))
761
(let* ((help-files-list (ess-get-help-topics-list ess-current-process-name))
762
(hlpobjs (ess-helpobjs-at-point help-files-list)))
763
(ess-completing-read p-string (append (delq nil hlpobjs) help-files-list)
764
nil nil nil nil (car hlpobjs)))
758
(if ess-get-help-topics-function
759
(let* ((help-files-list (funcall ess-get-help-topics-function ess-current-process-name))
760
(hlpobjs (ess-helpobjs-at-point help-files-list)))
761
(ess-completing-read p-string (append (delq nil hlpobjs) help-files-list)
762
nil nil nil nil (car hlpobjs)))
763
;; (string-match "\\(XLS\\)\\|\\(STA\\)\\|\\(SAS\\)" ess-language)
764
(read-string (format "%s: " p-string))
767
767
;;*;; Utility functions
768
(defun ess-get-help-topics-list (name)
768
(defun ess-get-S-help-topics (&optional name)
769
769
"Return a list of current S help topics associated with process NAME.
770
770
If `ess-sp-change' is non-nil or `ess-help-topics-list' is nil, (re)-populate
771
771
the latter and return it. Otherwise, return `ess-help-topics-list'."
773
(setq name (or name ess-local-process-name))
773
774
(set-buffer (process-buffer (get-ess-process name)))
774
775
(ess-make-buffer-current)
775
776
(ess-write-to-dribble-buffer
776
(format "(ess-get-help-topics-list %s) .." name))
777
(format "(ess-get-S-help-topics %s) .." name))
777
778
(if (or (not ess-help-topics-list) ess-sp-change)
778
(setq ess-help-topics-list
779
(setq ess-help-topics-list
780
781
(append (ess-get-object-list name 'exclude-1st)
781
782
(ess-get-help-files-list)