forked from jdtsmith/idlwave
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathidlw-shell.el
4783 lines (4301 loc) · 177 KB
/
idlw-shell.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;; idlw-shell.el --- run IDL as an inferior process of Emacs.
;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
;; 2009 Free Software Foundation, Inc.
;; Authors: J.D. Smith
;; Carsten Dominik
;; Chris Chase
;; Maintainer: J.D. Smith
;; Version: VERSIONTAG
;; Keywords: processes
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; This mode is for IDL version 5 or later. It should work on
;; Emacs>20.3 or XEmacs>20.4.
;;
;; Runs IDL as an inferior process of Emacs, much like the Emacs
;; `shell' or `telnet' commands. Provides command history and
;; searching. Provides debugging commands available in buffers
;; visiting IDL procedure files, e.g., breakpoint setting, stepping,
;; execution until a certain line, printing expressions under point,
;; visual line pointer for current execution line, etc.
;;
;; Documentation should be available online with `M-x idlwave-info'.
;;
;; New versions of IDLWAVE, documentation, and more information
;; available from:
;; http://github.com/jdtsmith/idlwave
;;
;; INSTALLATION:
;; =============
;;
;; Follow the instructions in the INSTALL file of the distribution.
;; In short, put this file on your load path and add the following
;; lines to your .emacs file:
;;
;; (autoload 'idlwave-shell "idlw-shell" "IDLWAVE Shell" t)
;;
;;
;; SOURCE
;; ======
;;
;; The newest version of this file can be found on the maintainers
;; web site.
;;
;; http://github.com/jdtsmith/idlwave
;;
;; DOCUMENTATION
;; =============
;;
;; IDLWAVE is documented online in info format.
;; A printable version of the documentation is available from the
;; maintainers webpage (see under SOURCE)
;;
;;
;; KNOWN PROBLEMS
;; ==============
;;
;; Under XEmacs the Debug menu in the shell does not display the
;; keybindings in the prefix map. There bindings are available anyway - so
;; it is a bug in XEmacs.
;; The Debug menu in source buffers *does* display the bindings correctly.
;;
;;
;; CUSTOMIZATION VARIABLES
;; =======================
;;
;; IDLWAVE has customize support - so if you want to learn about
;; the variables which control the behavior of the mode, use
;; `M-x idlwave-customize'.
;;
;;--------------------------------------------------------------------------
;;
;;; Code:
(require 'comint)
(require 'idlwave)
(eval-when-compile (require 'cl))
(defvar idlwave-shell-have-new-custom nil)
;;; Customizations: idlwave-shell group
;; General/Misc. customizations
(defgroup idlwave-shell-general-setup nil
"General setup of the Shell interaction for IDLWAVE/Shell."
:prefix "idlwave-shell"
:group 'idlwave)
(defcustom idlwave-shell-prompt-pattern "^\r? ?IDL> "
"*Regexp to match IDL prompt at beginning of a line.
For example, \"^\r?IDL> \" or \"^\r?WAVE> \".
The \"^\r?\" is needed, to indicate the beginning of the line, with
optional return character (which IDL seems to output randomly).
This variable is used to initialize `comint-prompt-regexp' in the
process buffer.
This is a fine thing to set in your `.emacs' file."
:group 'idlwave-shell-general-setup
:type 'regexp)
(defcustom idlwave-shell-process-name "idl"
"*Name to be associated with the IDL process. The buffer for the
process output is made by surrounding this name with `*'s."
:group 'idlwave-shell-general-setup
:type 'string)
;; (defcustom idlwave-shell-automatic-start...) See idlwave.el
(defcustom idlwave-shell-use-dedicated-window nil
"*Non-nil means, never replace the shell frame with another buffer."
:group 'idlwave-shell-general-setup
:type 'boolean)
(defcustom idlwave-shell-use-dedicated-frame nil
"*Non-nil means, IDLWAVE should use a special frame to display shell buffer."
:group 'idlwave-shell-general-setup
:type 'boolean)
(defcustom idlwave-shell-frame-parameters
'((height . 30) (unsplittable . nil))
"The frame parameters for a dedicated idlwave-shell frame.
See also `idlwave-shell-use-dedicated-frame'.
The default makes the frame splittable, so that completion works correctly."
:group 'idlwave-shell-general-setup
:type '(repeat
(cons symbol sexp)))
(defcustom idlwave-shell-buffer-height-frac nil
"The fraction of the current frame height to allocate to a
non-dedicated shell buffer window. Only relevant if
`idlwave-shell-use-dedicated-frame' is nil"
:group 'idlwave-shell-general-setup
:type '(choice
(const :tag "Default" nil)
(float :tag "Fraction")))
(defcustom idlwave-shell-raise-frame t
"*Non-nil means, `idlwave-shell' raises the frame showing the shell window."
:group 'idlwave-shell-general-setup
:type 'boolean)
(defcustom idlwave-shell-arrows-do-history t
"*Non-nil means UP and DOWN arrows move through command history.
This variable can have 3 values:
nil Arrows just move the cursor
t Arrows force the cursor back to the current command line and
walk the history
'cmdline When the cursor is in the current command line, arrows walk the
history. Everywhere else in the buffer, arrows move the cursor."
:group 'idlwave-shell-general-setup
:type '(choice
(const :tag "never" nil)
(const :tag "everywhere" t)
(const :tag "in command line only" cmdline)))
;; FIXME: add comint-input-ring-size?
(defcustom idlwave-shell-use-toolbar t
"*Non-nil means, use the debugging toolbar in all IDL related buffers.
Starting the shell will then add the toolbar to all idlwave-mode buffers.
Exiting the shell will removed everywhere.
Available on XEmacs and on Emacs 21.x or later.
At any time you can toggle the display of the toolbar with
`C-c C-d C-t' (`idlwave-shell-toggle-toolbar')."
:group 'idlwave-shell-general-setup
:type 'boolean)
(defcustom idlwave-shell-temp-pro-prefix "/tmp/idltemp"
"*The prefix for temporary IDL files used when compiling regions.
It should be an absolute pathname.
The full temporary file name is obtained by using `make-temp-file'
so that the name will be unique among multiple Emacs processes."
:group 'idlwave-shell-general-setup
:type 'string)
(defvar idlwave-shell-fix-inserted-breaks nil
"*OBSOLETE VARIABLE, is no longer used.
The documentation of this variable used to be:
If non-nil then run `idlwave-shell-remove-breaks' to clean up IDL messages.")
(defcustom idlwave-shell-prefix-key "\C-c\C-d"
"*The prefix key for the debugging map `idlwave-shell-mode-prefix-map'.
This variable must already be set when idlwave-shell.el is loaded.
Setting it in the mode-hook is too late."
:group 'idlwave-shell-general-setup
:type 'string)
(defcustom idlwave-shell-activate-prefix-keybindings t
"Non-nil means, the debug commands will be bound to the prefix key.
The prefix key itself is given in the option `idlwave-shell-prefix-key'.
So by default setting a breakpoint will be on C-c C-d C-b."
:group 'idlwave-shell-general-setup
:type 'boolean)
(defcustom idlwave-shell-automatic-electric-debug 'breakpoint
"Enter the electric-debug minor mode automatically.
This occurs at a breakpoint or any other halt. The mode is exited
upon return to the main level. Can be set to 'breakpoint to enter
electric debug mode only when breakpoints are tripped."
:group 'idlwave-shell-general-setup
:type '(choice
(const :tag "never" nil)
(const :tag "always" t)
(const :tag "for breakpoints only" breakpoint)))
(defcustom idlwave-shell-electric-zap-to-file t
"When entering electric debug mode, select the window displaying the
file at which point is stopped. This takes point away from the shell
window, but is useful for stepping, etc."
:group 'idlwave-shell-general-setup
:type 'boolean)
;; (defcustom idlwave-shell-debug-modifiers... See idlwave.el
(defvar idlwave-shell-activate-alt-keybindings nil
"Obsolete variable. See `idlwave-shell-debug-modifiers'.")
(defcustom idlwave-shell-use-truename nil
"*Non-nil means, use use `file-truename' when looking for buffers.
If this variable is non-nil, Emacs will use the function `file-truename' to
resolve symbolic links in the file paths printed by e.g., STOP commands.
This means, unvisited files will be loaded under their truename.
However, when a file is already visited under a different name, IDLWAVE will
reuse that buffer.
This option was once introduced in order to avoid multiple buffers visiting
the same file. However, IDLWAVE no longer makes this mistake, so it is safe
to set this option to nil."
:group 'idlwave-shell-general-setup
:type 'boolean)
(defcustom idlwave-shell-file-name-chars "~/A-Za-z0-9+:_.$#%={}\\- "
"The characters allowed in file names, as a string.
Used for file name completion. Must not contain `'', `,' and `\"'
because these are used as separators by IDL."
:group 'idlwave-shell-general-setup
:type 'string)
(defcustom idlwave-shell-mode-hook '()
"*Hook for customizing `idlwave-shell-mode'."
:group 'idlwave-shell-general-setup
:type 'hook)
(defcustom idlwave-shell-graphics-window-size '(500 400)
"Size of IDL graphics windows popped up by special IDLWAVE command.
The command is `C-c C-d C-f' and accepts as a prefix the window nr.
A command like `WINDOW,N,xsize=XX,ysize=YY' is sent to IDL."
:group 'idlwave-shell-general-setup
:type '(list
(integer :tag "x size")
(integer :tag "y size")))
;; Commands Sent to Shell... etc.
(defgroup idlwave-shell-command-setup nil
"Setup for command parameters of the Shell interaction for IDLWAVE."
:prefix "idlwave-shell"
:group 'idlwave)
(defcustom idlwave-shell-initial-commands "!more=0 & defsysv,'!ERROR_STATE',EXISTS=__e & if __e then begin & !ERROR_STATE.MSG_PREFIX=\"% \" & delvar,__e & endif"
"Initial commands, separated by newlines, to send to IDL.
This string is sent to the IDL process by `idlwave-shell-mode' which is
invoked by `idlwave-shell'."
:group 'idlwave-shell-command-setup
:type 'string)
(defcustom idlwave-shell-save-command-history t
"Non-nil means preserve command history between sessions.
The file `idlwave-shell-command-history-file' is used to save and restore
the history."
:group 'idlwave-shell-command-setup
:type 'boolean)
(defcustom idlwave-shell-command-history-file "idlwhist"
"The file in which the command history of the idlwave shell is saved.
In order to change the size of the history, see the variable
`comint-input-ring-size'.
The history is only saved if the variable `idlwave-shell-save-command-history'
is non-nil."
:group 'idlwave-shell-command-setup
:type 'file)
(defcustom idlwave-shell-show-commands
'(run misc breakpoint)
"*A list of command types to show output from in the shell.
Possibilities are 'run, 'debug, 'breakpoint, and 'misc. Unselected
types are not displayed in the shell. The type 'everything causes all
the copious shell traffic to be displayed."
:group 'idlwave-shell-command-setup
:type '(choice
(const everything)
(set :tag "Checklist" :greedy t
(const :tag "All .run and .compile commands" run)
(const :tag "All breakpoint commands" breakpoint)
(const :tag "All debug and stepping commands" debug)
(const :tag "Close, window, retall, etc. commands" misc))))
(defcustom idlwave-shell-max-print-length 200
"Maximum number of array elements to print when examining."
:group 'idlwave-shell-command-setup
:type 'integer)
(defcustom idlwave-shell-examine-alist
`(("Print" . ,(concat "idlwave_print_safe,___,"
(number-to-string
idlwave-shell-max-print-length)))
("Help" . "help,___")
("Structure Help" . "help,___,/STRUCTURE")
("Dimensions" . "print,size(___,/DIMENSIONS)")
("Type" . "print,size(___,/TNAME)")
("N_Elements" . "print,n_elements(___)")
("All Size Info" . "help,(__IWsz__=size(___,/STRUCTURE)),/STRUCTURE & print,__IWsz__.DIMENSIONS")
("Ptr Valid" . "print,ptr_valid(___)")
("Arg Present" . "print,arg_present(___)")
("Widget Valid" . "print,widget_info(___,/VALID)")
("Widget Geometry" . "help,widget_info(___,/GEOMETRY)"))
"Alist of special examine commands for popup selection.
The keys are used in the selection popup created by
`idlwave-shell-examine-select', and the corresponding value is sent as
a command to the shell, with special sequence `___' replaced by the
expression being examined."
:group 'idlwave-shell-command-setup
:type '(repeat
(cons
(string :tag "Label ")
(string :tag "Command"))))
(defvar idlwave-shell-print-expression-function nil
"*OBSOLETE VARIABLE, is no longer used.")
(defcustom idlwave-shell-separate-examine-output t
"*Non-nil means, put output of examine commands in their own buffer."
:group 'idlwave-shell-command-setup
:type 'boolean)
(defcustom idlwave-shell-comint-settings
'((comint-scroll-to-bottom-on-input . t)
(comint-scroll-to-bottom-on-output . t)
(comint-scroll-show-maximum-output . nil)
(comint-prompt-read-only . t))
"Alist of special settings for the comint variables in the IDLWAVE Shell.
Each entry is a cons cell with the name of a variable and a value.
The function `idlwave-shell-mode' will make local variables out of each entry.
Changes to this variable will only be active when the shell buffer is
newly created."
:group 'idlwave-shell-command-setup
:type '(repeat
(cons variable sexp)))
(defcustom idlwave-shell-query-for-class t
"*Non-nil means query the shell for object class on object completions."
:group 'idlwave-shell-command-setup
:type 'boolean)
(defcustom idlwave-shell-use-input-mode-magic nil
"*Non-nil means, IDLWAVE should check for input mode spells in output.
The spells are strings printed by your IDL program and matched
by the regular expressions in `idlwave-shell-input-mode-spells'.
When these expressions match, IDLWAVE switches to character input mode and
back, respectively. See `idlwave-shell-input-mode-spells' for details."
:group 'idlwave-shell-command-setup
:type 'boolean)
(defcustom idlwave-shell-input-mode-spells
'("^<onechar>$" "^<chars>$" "^</chars>$")
"The three regular expressions which match the magic spells for input modes.
When the first regexp matches in the output stream of IDL, IDLWAVE
prompts for a single character and sends it immediately to IDL, similar
to the command \\[idlwave-shell-send-char].
When the second regexp matches, IDLWAVE switches to a blocking
single-character input mode. This is the same mode which can be entered
manually with \\[idlwave-shell-char-mode-loop].
This input mode exits when the third regexp matches in the output,
or when the IDL prompt is encountered.
The variable `idlwave-shell-use-input-mode-magic' must be non-nil to enable
scanning for these expressions. If the IDL program produces lots of
output, shell operation may be slowed down.
This mechanism is useful for correct interaction with the IDL function
GET_KBRD, because in normal operation IDLWAVE only sends \\n terminated
strings. Here is some example code which makes use of the default spells.
print,'<chars>' ; Make IDLWAVE switch to character mode
REPEAT BEGIN
A = GET_KBRD(1)
PRINT, BYTE(A)
ENDREP UNTIL A EQ 'q'
print,'</chars>' ; Make IDLWAVE switch back to line mode
print,'Quit the program, y or n?'
print,'<onechar>' ; Ask IDLWAVE to send one character
answer = GET_KBRD(1)
Since the IDLWAVE shell defines the system variable `!IDLWAVE_VERSION',
you could actually check if you are running under Emacs before printing
the magic strings. Here is a procedure which uses this.
Usage:
======
idlwave_char_input ; Make IDLWAVE send one character
idlwave_char_input,/on ; Start the loop to send characters
idlwave_char_input,/off ; End the loop to send characters
pro idlwave_char_input,on=on,off=off
;; Test if we are running under Emacs
defsysv,'!idlwave_version',exists=running_emacs
if running_emacs then begin
if keyword_set(on) then print,'<chars>' $
else if keyword_set(off) then print,'</chars>' $
else print,'<onechar>'
endif
end"
:group 'idlwave-shell-command-setup
:type '(list
(regexp :tag "One-char regexp")
(regexp :tag "Char-mode regexp")
(regexp :tag "Line-mode regexp")))
(defcustom idlwave-shell-breakpoint-popup-menu t
"*If non-nil, provide a menu on mouse-3 on breakpoint lines, and
popup help text on the line."
:group 'idlwave-shell-command-setup
:type 'boolean)
(defcustom idlwave-shell-reset-no-prompt nil
"If non-nil, skip the yes/no prompt when resetting the IDL session."
:group 'idlwave-shell-command-setup
:type 'boolean)
;; Breakpoint Overlays etc
(defgroup idlwave-shell-highlighting-and-faces nil
"Highlighting and faces used by the IDLWAVE Shell mode."
:prefix "idlwave-shell"
:group 'idlwave)
(defcustom idlwave-shell-mark-stop-line t
"*Non-nil means, mark the source code line where IDL is currently stopped.
Value decides about the method which is used to mark the line. Valid values
are:
nil Do not mark the line
'arrow Use the overlay arrow
'face Use `idlwave-shell-stop-line-face' to highlight the line.
t Use what IDLWAVE thinks is best. Will be a face where possible,
otherwise the overlay arrow.
The overlay-arrow has the disadvantage to hide the first chars of a line.
Since many people do not have the main block of IDL programs indented,
a face highlighting may be better.
In Emacs 21, the overlay arrow is displayed in a special area and never
hides any code, so setting this to 'arrow on Emacs 21 sounds like a good idea."
:group 'idlwave-shell-highlighting-and-faces
:type '(choice
(const :tag "No marking" nil)
(const :tag "Use overlay arrow" arrow)
(const :tag "Highlight with face" face)
(const :tag "Face or arrow." t)))
(defcustom idlwave-shell-overlay-arrow ">"
"*The overlay arrow to display at source lines where execution halts.
We use a single character by default, since the main block of IDL procedures
often has no indentation. Where possible, IDLWAVE will use overlays to
display the stop-lines. The arrow is only used on character-based terminals.
See also `idlwave-shell-use-overlay-arrow'."
:group 'idlwave-shell-highlighting-and-faces
:type 'string)
(defcustom idlwave-shell-stop-line-face 'highlight
"*The face for `idlwave-shell-stop-line-overlay'.
Allows you to choose the font, color and other properties for
line where IDL is stopped. See also `idlwave-shell-mark-stop-line'."
:group 'idlwave-shell-highlighting-and-faces
:type 'symbol)
(defcustom idlwave-shell-electric-stop-color "Violet"
"*The color for the default face or overlay arrow when stopped."
:group 'idlwave-shell-highlighting-and-faces
:type 'string)
(defface idlwave-shell-electric-stop-line
`((((class color))
:background ,idlwave-shell-electric-stop-color
:box (:line-width -1 :style released-button))
(t
:box (:line-width -1 :style released-button)))
"The default face for `idlwave-shell-stop-line-overlay' when in
electric debug mode.")
(defcustom idlwave-shell-electric-stop-line-face
'idlwave-shell-electric-stop-line
"*The face for `idlwave-shell-stop-line-overlay' when in electric debug mode.
Allows you to choose the font, color and other properties for the line
where IDL is stopped, when in Electric Debug Mode."
:group 'idlwave-shell-highlighting-and-faces
:type 'symbol)
(defcustom idlwave-shell-mark-breakpoints t
"*Non-nil means, mark breakpoints in the source files.
Valid values are:
nil Do not mark breakpoints.
'face Highlight line with `idlwave-shell-breakpoint-face'.
'glyph Red dot at the beginning of line. If the display does not
support glyphs, will use 'face instead.
t Glyph when possible, otherwise face (same effect as 'glyph)."
:group 'idlwave-shell-highlighting-and-faces
:type '(choice
(const :tag "No marking" nil)
(const :tag "Highlight with face" face)
(const :tag "Display glyph (red dot)" glyph)
(const :tag "Glyph or face." t)))
(defvar idlwave-shell-use-breakpoint-glyph t
"Obsolete variable. See `idlwave-shell-mark-breakpoints'.")
(defcustom idlwave-shell-breakpoint-face 'idlwave-shell-bp
"*The face for breakpoint lines in the source code.
Allows you to choose the font, color and other properties for
lines which have a breakpoint. See also `idlwave-shell-mark-breakpoints'."
:group 'idlwave-shell-highlighting-and-faces
:type 'symbol)
(if (not idlwave-shell-have-new-custom)
;; Just copy the underline face to be on the safe side.
(copy-face 'underline 'idlwave-shell-bp)
;; We have the new customize - use it to define a customizable face
(defface idlwave-shell-bp
'((((class color)) (:foreground "Black" :background "Pink"))
(t (:underline t)))
"Face for highlighting lines with breakpoints."
:group 'idlwave-shell-highlighting-and-faces))
(defcustom idlwave-shell-disabled-breakpoint-face
'idlwave-shell-disabled-bp
"*The face for disabled breakpoint lines in the source code.
Allows you to choose the font, color and other properties for
lines which have a breakpoint. See also `idlwave-shell-mark-breakpoints'."
:group 'idlwave-shell-highlighting-and-faces
:type 'symbol)
(if (not idlwave-shell-have-new-custom)
;; Just copy the underline face to be on the safe side.
(copy-face 'underline 'idlwave-shell-disabled-bp)
;; We have the new customize - use it to define a customizable face
(defface idlwave-shell-disabled-bp
'((((class color)) (:foreground "Black" :background "gray"))
(t (:underline t)))
"Face for highlighting lines with breakpoints."
:group 'idlwave-shell-highlighting-and-faces))
(defcustom idlwave-shell-expression-face 'secondary-selection
"*The face for `idlwave-shell-expression-overlay'.
Allows you to choose the font, color and other properties for
the expression printed by IDL."
:group 'idlwave-shell-highlighting-and-faces
:type 'symbol)
(defcustom idlwave-shell-output-face 'secondary-selection
"*The face for `idlwave-shell-output-overlay'.
Allows you to choose the font, color and other properties for
the expression output by IDL."
:group 'idlwave-shell-highlighting-and-faces
:type 'symbol)
;;; End user customization variables
;;; External variables
(defvar comint-last-input-start)
(defvar comint-last-input-end)
;; Other variables
(defvar idlwave-shell-temp-pro-file nil
"Absolute pathname for temporary IDL file for compiling regions")
(defvar idlwave-shell-temp-rinfo-save-file nil
"Absolute pathname for temporary IDL file save file for routine_info.
This is used to speed up the reloading of the routine info procedure
before use by the shell.")
(defun idlwave-shell-temp-file (type)
"Return a temp file, creating it if necessary.
TYPE is either 'pro' or 'rinfo', and `idlwave-shell-temp-pro-file' or
`idlwave-shell-temp-rinfo-save-file' is set (respectively)."
(cond
((eq type 'rinfo)
(or idlwave-shell-temp-rinfo-save-file
(setq idlwave-shell-temp-rinfo-save-file
(idlwave-shell-make-temp-file idlwave-shell-temp-pro-prefix))))
((eq type 'pro)
(or idlwave-shell-temp-pro-file
(setq idlwave-shell-temp-pro-file
(idlwave-shell-make-temp-file idlwave-shell-temp-pro-prefix))))
(t (error "Wrong argument (idlwave-shell-temp-file): %s"
(symbol-name type)))))
(defun idlwave-shell-make-temp-file (prefix)
"Create a temporary file."
; Hard coded make-temp-file for Emacs<21
(if (fboundp 'make-temp-file)
(make-temp-file prefix)
(let (file
(temp-file-dir (if (boundp 'temporary-file-directory)
temporary-file-directory
"/tmp")))
(while (condition-case ()
(progn
(setq file
(make-temp-name
(expand-file-name prefix temp-file-dir)))
(if (featurep 'xemacs)
(write-region "" nil file nil 'silent nil)
(write-region "" nil file nil 'silent nil 'excl))
nil)
(file-already-exists t))
;; the file was somehow created by someone else between
;; `make-temp-name' and `write-region', let's try again.
nil)
file)))
(defvar idlwave-shell-dirstack-query "cd,current=___cur & print,___cur"
"Command used by `idlwave-shell-resync-dirs' to query IDL for
the directory stack.")
(defvar idlwave-shell-path-query "print,'PATH:<'+transpose(expand_path(!PATH,/ARRAY))+'>' & print,'SYSDIR:<'+!dir+'>'"
"The command which gets !PATH and !DIR info from the shell.")
(defvar idlwave-shell-mode-line-info nil
"Additional info displayed in the mode line.")
(defvar idlwave-shell-default-directory nil
"The default directory in the idlwave-shell buffer, of outside use.")
(defvar idlwave-shell-last-save-and-action-file nil
"The last file which was compiled with `idlwave-shell-save-and-...'.")
;; Highlighting uses overlays. When necessary, require the emulation.
(if (not (fboundp 'make-overlay))
(condition-case nil
(require 'overlay)
(error nil)))
(defvar idlwave-shell-stop-line-overlay nil
"The overlay for where IDL is currently stopped.")
(defvar idlwave-shell-is-stopped nil)
(defvar idlwave-shell-expression-overlay nil
"The overlay for the examined expression.")
(defvar idlwave-shell-output-overlay nil
"The overlay for the last IDL output.")
;; If these were already overlays, delete them. This probably means that we
;; are reloading this file.
(if (overlayp idlwave-shell-stop-line-overlay)
(delete-overlay idlwave-shell-stop-line-overlay))
(if (overlayp idlwave-shell-expression-overlay)
(delete-overlay idlwave-shell-expression-overlay))
(if (overlayp idlwave-shell-output-overlay)
(delete-overlay idlwave-shell-output-overlay))
;; Set to nil initially
(setq idlwave-shell-stop-line-overlay nil
idlwave-shell-expression-overlay nil
idlwave-shell-output-overlay nil)
;; Define the shell stop overlay. When left nil, the arrow will be used.
(cond
((or (null idlwave-shell-mark-stop-line)
(eq idlwave-shell-mark-stop-line 'arrow))
;; Leave the overlay nil
nil)
((eq idlwave-shell-mark-stop-line 'face)
;; Try to use a face. If not possible, arrow will be used anyway
;; So who can display faces?
(when (or (featurep 'xemacs) ; XEmacs can do also ttys
(fboundp 'tty-defined-colors) ; Emacs 21 as well
(display-graphic-p)) ; Window systems always
(progn
(setq idlwave-shell-stop-line-overlay (make-overlay 1 1))
(overlay-put idlwave-shell-stop-line-overlay
'face idlwave-shell-stop-line-face))))
(t
;; IDLWAVE may decide. Will use a face plus arrow on window systems,
;; just arrow elsewhere
(if (display-graphic-p)
(progn
(setq idlwave-shell-stop-line-overlay (make-overlay 1 1))
(overlay-put idlwave-shell-stop-line-overlay
'face idlwave-shell-stop-line-face)))))
;; Now the expression and output overlays
(setq idlwave-shell-expression-overlay (make-overlay 1 1))
(overlay-put idlwave-shell-expression-overlay
'face idlwave-shell-expression-face)
(overlay-put idlwave-shell-expression-overlay
'priority 1)
(setq idlwave-shell-output-overlay (make-overlay 1 1))
(overlay-put idlwave-shell-output-overlay
'face idlwave-shell-output-face)
(copy-face idlwave-shell-stop-line-face
'idlwave-shell-pending-stop)
(copy-face idlwave-shell-electric-stop-line-face
'idlwave-shell-pending-electric-stop)
(set-face-background 'idlwave-shell-pending-stop "gray70")
(set-face-background 'idlwave-shell-pending-electric-stop "gray70")
(defvar idlwave-shell-bp-query "help,/breakpoints"
"Command to obtain list of breakpoints.")
(defvar idlwave-shell-command-output nil
"String for accumulating current command output.")
(defvar idlwave-shell-sentinel-hook nil
"Hook run when the IDL process exits.")
(defvar idlwave-shell-accumulation nil
"Accumulate last line of output.")
(defvar idlwave-shell-command-line-to-execute nil)
(defvar idlwave-shell-cleanup-hook nil
"List of functions to do cleanup when the shell exits.")
(defvar idlwave-shell-pending-commands nil
"List of commands to be sent to IDL.
Each element of the list is list of \(CMD PCMD HIDE SHOW-IF-ERROR
REDISPLAY\), where CMD is a string to be sent to IDL and PCMD is
a post-command to be called after CMD completes. If HIDE is
non-nil, hide the output from command CMD. If SHOW-IF-ERROR is
non-nil, show the full output if it contains an error. If
REDISPLAY is non-nil, clear the current stopped line position if
no position is recognized (unless it is 'disable, in which case
don't update line position unless an error is found). PCMD,
HIDE, and SHOW-IF-ERROR are optional.")
(defvar idlwave-shell-current-command nil
"Current command being executed.
A list consisting of a single element from the list of pending
commands, `idlwave-shell-pending-commands'.")
(defvar idlwave-shell-completed-command nil
"The most recently completed command.
Same format as current-command. Corresponds to command-output.")
(defun idlwave-shell-buffer ()
"Name of buffer associated with IDL process.
The name of the buffer is made by surrounding `idlwave-shell-process-name'
with `*'s."
(concat "*" idlwave-shell-process-name "*"))
(defvar idlwave-shell-ready nil
"If non-nil can send next command to IDL process.")
;;; The following are the types of messages we attempt to catch to
;;; resync our idea of where IDL execution currently is.
;;;
(defvar idlwave-shell-halt-frame nil
"The frame associated with halt/breakpoint messages.")
(defvar idlwave-shell-step-frame nil
"The frame associated with step messages.")
(defvar idlwave-shell-trace-frame nil
"The frame associated with trace messages.")
(defconst idlwave-shell-halt-messages
'("^% Interrupted at:"
"^% Stepped to:"
"^% Skipped to:"
"^% Stop encountered:"
)
"*A list of regular expressions matching IDL messages.
These are the messages containing file and line information where
IDL is currently stopped.")
(defconst idlwave-shell-halt-messages-re
(mapconcat 'identity idlwave-shell-halt-messages "\\|")
"The regular expression computed from `idlwave-shell-halt-messages'.")
(defconst idlwave-shell-trace-message-re
"^% At " ;; First line of a trace message
"*A regular expression matching IDL trace messages. These are the
messages containing file and line information of a current
traceback.")
(defconst idlwave-shell-step-messages
'("^% Stepped to:"
)
"*A list of regular expressions matching stepped execution messages.
These are IDL messages containing file and line information where
IDL has currently stepped.")
(defvar idlwave-shell-break-message "^% Breakpoint at:"
"*Regular expression matching an IDL breakpoint message line.")
(defconst idlwave-shell-electric-debug-help
" ==> IDLWAVE Electric Debug Mode Help <==
Break Point Setting and Clearing:
b Set breakpoint ([C-u b] for conditional, [C-n b] nth hit, etc.).
d Clear nearby breakpoint.
a Clear all breakpoints.
i Set breakpoint in routine named here.
j Set breakpoint at beginning of containing routine.
\\ Toggle breakpoint disable
] Go to next breakpoint in file.
[ Go to previous breakpoint in file.
Stepping, Continuing, and the Stack:
s or SPACE Step, into function calls.
n Step, over function calls.
k Skip one statement.
m Continue to end of function.
o Continue past end of function.
u Continue to end of block.
h Continue to line at cursor position.
r Continue execution to next breakpoint, if any.
+ or = Show higher level in calling stack.
- or _ Show lower level in calling stack.
Examining Expressions (with prefix for examining the region):
p Print expression near point or in region ([C-u p]).
? Help on expression near point or in region ([C-u ?]).
x Examine expression near point or in region ([C-u x]) with
letter completion of the examine type.
e Prompt for an expression to print.
Miscellaneous:
q Quit - end debugging session and return to the Shell's main level.
v Turn Electric Debugging Mode off (C-c C-d C-v to return).
t Print a calling-level traceback in the shell.
z Reset IDL.
C-? Show this help menu.")
(defvar idlwave-shell-bp-alist)
;(defvar idlwave-shell-post-command-output)
(defvar idlwave-shell-sources-alist)
(defvar idlwave-shell-menu-def)
(defvar idlwave-shell-mode-menu)
(defvar idlwave-shell-initial-commands)
(defvar idlwave-shell-syntax-error)
(defvar idlwave-shell-other-error)
(defvar idlwave-shell-error-buffer)
(defvar idlwave-shell-error-last)
(defvar idlwave-shell-bp-buffer)
(defvar idlwave-shell-command-buffer)
(defvar idlwave-shell-sources-query)
(defvar idlwave-shell-mode-map)
(defvar idlwave-shell-calling-stack-index)
(defvar idlwave-shell-only-prompt-pattern nil)
(defvar tool-bar-map)
(defun idlwave-shell-mode ()
"Major mode for interacting with an inferior IDL process.
1. Shell Interaction
-----------------
RET after the end of the process' output sends the text from the
end of process to the end of the current line. RET before end of
process output copies the current line (except for the prompt) to
the end of the buffer.
Command history, searching of previous commands, command line
editing are available via the comint-mode key bindings, by default
mostly on the key `C-c'. Command history is also available with
the arrow keys UP and DOWN.
2. Completion
----------
TAB and M-TAB do completion of IDL routines, classes and keywords -
similar to M-TAB in `idlwave-mode'. In executive commands and
strings, it completes file names. Abbreviations are also expanded
like in `idlwave-mode'.
3. Routine Info
------------
`\\[idlwave-routine-info]' displays information about an IDL routine near point,
just like in `idlwave-mode'. The module used is the one at point or
the one whose argument list is being edited.
To update IDLWAVE's knowledge about compiled or edited modules, use
\\[idlwave-update-routine-info].
\\[idlwave-find-module] find the source of a module.
\\[idlwave-resolve] tells IDL to compile an unresolved module.
\\[idlwave-context-help] shows the online help on the item at
point, if online help has been installed.
4. Debugging
---------
A complete set of commands for compiling and debugging IDL programs
is available from the menu. Also keybindings starting with a
`C-c C-d' prefix are available for most commands in the *idl* buffer
and also in source buffers. The best place to learn about the
keybindings is again the menu.
On Emacs versions where this is possible, a debugging toolbar is
installed.
When IDL is halted in the middle of a procedure, the corresponding
line of that procedure file is displayed with an overlay in another
window. Breakpoints are also highlighted in the source.
\\[idlwave-shell-resync-dirs] queries IDL in order to change Emacs current directory
to correspond to the IDL process current directory.
5. Expression Examination
----------------------
Expressions near point can be examined with print,
\\[idlwave-shell-print] or \\[idlwave-shell-mouse-print] with the
mouse, help, \\[idlwave-shell-help-expression] or
\\[idlwave-shell-mouse-help] with the mouse, or with a
configureable set of custom examine commands using
\\[idlwave-shell-examine-select]. The mouse examine commands can
also work by click and drag, to select an expression for
examination.
6. Hooks
-----
Turning on `idlwave-shell-mode' runs `comint-mode-hook' and
`idlwave-shell-mode-hook' (in that order).
7. Documentation and Customization
-------------------------------
Info documentation for this package is available. Use \\[idlwave-info]
to display (complain to your sysadmin if that does not work).
For Postscript and HTML versions of the documentation, check IDLWAVE's
homepage at URL `http://github.com/jdtsmith/idlwave'.
IDLWAVE has customize support - see the group `idlwave'.
8. Keybindings
-----------
\\{idlwave-shell-mode-map}"
(interactive)
; Make sure config files and paths, etc. are available.
(idlwave-setup)
(unless (file-name-absolute-p idlwave-shell-command-history-file)
(setq idlwave-shell-command-history-file
(expand-file-name idlwave-shell-command-history-file
idlwave-config-directory)))
;; We don't do `kill-all-local-variables' here, because this is done by
;; comint
(setq comint-prompt-regexp idlwave-shell-prompt-pattern)
(setq comint-process-echoes t)
;; Can not use history expansion because "!" is used for system variables.
(setq comint-input-autoexpand nil)
; (setq comint-input-ring-size 64)
(make-local-variable 'comint-completion-addsuffix)
(set (make-local-variable 'completion-ignore-case) t)
(setq comint-completion-addsuffix '("/" . ""))
(setq comint-input-ignoredups t)
(setq comint-input-sender (function idlwave-shell-sender))
(setq major-mode 'idlwave-shell-mode)
(setq mode-name "IDL-Shell")
(setq idlwave-shell-mode-line-info nil)
(setq mode-line-format
'(""
mode-line-modified
mode-line-buffer-identification
" "
global-mode-string
" %[("
mode-name
mode-line-process