line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Emacs::Run; |
2
|
3
|
|
|
3
|
|
207288
|
use base qw( Class::Base ); |
|
3
|
|
|
|
|
9
|
|
|
3
|
|
|
|
|
5137
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
=head1 NAME |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
Emacs::Run - use emacs from perl via the shell |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 SYNOPSIS |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use Emacs::Run; |
11
|
|
|
|
|
|
|
my $er = Emacs::Run->new(); |
12
|
|
|
|
|
|
|
my $major_version = $er->emacs_major_version; |
13
|
|
|
|
|
|
|
if ($major_version > 22) { |
14
|
|
|
|
|
|
|
print "You have a recent version of emacs\n"; |
15
|
|
|
|
|
|
|
} |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# use extra emacs lisp libraries, then get emacs settings |
18
|
|
|
|
|
|
|
my $er = Emacs::Run->new({ |
19
|
|
|
|
|
|
|
emacs_libs => [ '~/lib/my-elisp.el', |
20
|
|
|
|
|
|
|
'/usr/lib/site-emacs/stuff.el' ], |
21
|
|
|
|
|
|
|
}); |
22
|
|
|
|
|
|
|
my $emacs_load_path_aref = $er->get_load_path; |
23
|
|
|
|
|
|
|
my $email = $er->get_variable( 'user-mail-address' ); |
24
|
|
|
|
|
|
|
my $name = $er->eval_function( 'user-full-name' ); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# suppress the use of the usual emacs init (e.g. ~/.emacs) |
27
|
|
|
|
|
|
|
my $er = Emacs::Run->new({ |
28
|
|
|
|
|
|
|
load_emacs_init => 0, |
29
|
|
|
|
|
|
|
}); |
30
|
|
|
|
|
|
|
my $result = $er->eval_elisp( '(print (+ 2 2))' ); # that's "4" |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# the eval_elisp_full_emacs method works with a full externally |
34
|
|
|
|
|
|
|
# spawned emacs (for unusual code that won't run under '--batch') |
35
|
|
|
|
|
|
|
my $elisp_initialize = |
36
|
|
|
|
|
|
|
qq{ |
37
|
|
|
|
|
|
|
(defvar my-temp-var "$text") |
38
|
|
|
|
|
|
|
(insert "The initialize elisp has no effect on output: you won't see this.") |
39
|
|
|
|
|
|
|
}; |
40
|
|
|
|
|
|
|
my $elisp = |
41
|
|
|
|
|
|
|
qq{ |
42
|
|
|
|
|
|
|
(insert my-temp-var) |
43
|
|
|
|
|
|
|
(downcase-region (point-min) (point-max)) |
44
|
|
|
|
|
|
|
(my-test-lib-do-something) |
45
|
|
|
|
|
|
|
}; |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
my @emacs_libs = ( $dot_emacs, 'my-test-lib' ); |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
my $er = Emacs::Run->new({ |
50
|
|
|
|
|
|
|
load_no_inits => 1, |
51
|
|
|
|
|
|
|
emacs_libs => \@emacs_libs, |
52
|
|
|
|
|
|
|
}); |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my $output_lines_aref = |
55
|
|
|
|
|
|
|
$er->eval_elisp_full_emacs( { |
56
|
|
|
|
|
|
|
elisp_initialize => $elisp_initialize, |
57
|
|
|
|
|
|
|
output_file => $name_list_file, # omit to use temp file |
58
|
|
|
|
|
|
|
elisp => $elisp, |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=head1 DESCRIPTION |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
Emacs::Run is a module that provides portable utilities to run |
63
|
|
|
|
|
|
|
emacs from perl as an external process. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
This module provides methods to allow perl code to: |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=over |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=item * |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Probe the system's emacs installation to get the installed |
72
|
|
|
|
|
|
|
version, the user's current load-path, and so on. |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=item * |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
Run chunks of emacs lisp code without worrying too much about the |
77
|
|
|
|
|
|
|
details of quoting issues and loading libraries and so on. |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=back |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Most of the routines here make use of the emacs "--batch" feature |
82
|
|
|
|
|
|
|
that runs emacs in a non-interactive mode. A few, such as |
83
|
|
|
|
|
|
|
L work by opening a full emacs window, |
84
|
|
|
|
|
|
|
and then killing it when it's no longer needed. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=head2 MOTIVATION |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
Periodically, I find myself interested in the strange world of |
89
|
|
|
|
|
|
|
running emacs code from perl. There's a mildly obscure feature of |
90
|
|
|
|
|
|
|
emacs command line invocations called "--batch" that essentially |
91
|
|
|
|
|
|
|
transforms emacs into a lisp interpreter. Additonal command-line |
92
|
|
|
|
|
|
|
options allow one to load files of elisp code and run pieces of code |
93
|
|
|
|
|
|
|
from the command-line. |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
I've found several uses for this tricks. You can use it to: |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=over |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=item * |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
Write perl tools to do automated installation of elisp packages. |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=item * |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
To test elisp code using a perl test harness. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=item * |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
To use code written in elisp that you don't want to rewrite in perl. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=back |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
This emacs command line invocation is a little language all of it's |
114
|
|
|
|
|
|
|
own, with just enough twists and turns to it that I've felt the need |
115
|
|
|
|
|
|
|
to write perl routines to help drive the process. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
At present, using Emacs::Run has one large portability advantage |
118
|
|
|
|
|
|
|
over writing your own emacs invocation code: there are some |
119
|
|
|
|
|
|
|
versions of GNU emacs 21 that require the "--no-splash" option, |
120
|
|
|
|
|
|
|
but using this option would cause an error with earlier versions. |
121
|
|
|
|
|
|
|
Emacs::Run handles the necessary probing for you, and generates |
122
|
|
|
|
|
|
|
the right invocation string for the system's installed emacs. |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
There are also some other, smaller advantages (e.g. automatic |
125
|
|
|
|
|
|
|
adjustment of the load-path to include the location of a package |
126
|
|
|
|
|
|
|
loaded as a file), and there may be more in the future. |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
A raw "emacs --batch" run would suppress most of the usual init |
129
|
|
|
|
|
|
|
files (but does load the essentially deprecated "site-start.pl"). |
130
|
|
|
|
|
|
|
Emacs::Run has the opposite bias: here we try to load all three |
131
|
|
|
|
|
|
|
kinds of init files, though each one of these can be shut-off |
132
|
|
|
|
|
|
|
individually if so desired. This is because one of the main |
133
|
|
|
|
|
|
|
intended uses is to let perl find out about things such as the |
134
|
|
|
|
|
|
|
user's emacs settings (notably, the B). And depending |
135
|
|
|
|
|
|
|
on your application, the performance hit of loading these files |
136
|
|
|
|
|
|
|
may not seem like such a big deal these days. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head2 METHODS |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=over |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=cut |
143
|
|
|
|
|
|
|
|
144
|
3
|
|
|
3
|
|
7497
|
use 5.8.0; |
|
3
|
|
|
|
|
15
|
|
|
3
|
|
|
|
|
253
|
|
145
|
3
|
|
|
3
|
|
18
|
use strict; |
|
3
|
|
|
|
|
11
|
|
|
3
|
|
|
|
|
135
|
|
146
|
3
|
|
|
3
|
|
20
|
use warnings; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
97
|
|
147
|
3
|
|
|
3
|
|
16
|
use Carp; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
232
|
|
148
|
3
|
|
|
3
|
|
2485
|
use Data::Dumper; |
|
3
|
|
|
|
|
12328
|
|
|
3
|
|
|
|
|
181
|
|
149
|
3
|
|
|
3
|
|
5531
|
use Hash::Util qw( lock_keys unlock_keys ); |
|
3
|
|
|
|
|
14616
|
|
|
3
|
|
|
|
|
24
|
|
150
|
3
|
|
|
3
|
|
365
|
use File::Basename qw( fileparse basename dirname ); |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
3083
|
|
151
|
3
|
|
|
3
|
|
151
|
use File::Spec; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
83
|
|
152
|
3
|
|
|
3
|
|
39
|
use Cwd qw( cwd abs_path ); |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
1070
|
|
153
|
3
|
|
|
3
|
|
22
|
use List::Util qw( first ); |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
398
|
|
154
|
3
|
|
|
3
|
|
5572
|
use Env qw( $HOME ); |
|
3
|
|
|
|
|
16906
|
|
|
3
|
|
|
|
|
19
|
|
155
|
3
|
|
|
3
|
|
16462
|
use List::MoreUtils qw( any ); |
|
3
|
|
|
|
|
12291
|
|
|
3
|
|
|
|
|
310
|
|
156
|
3
|
|
|
3
|
|
3879
|
use File::Temp qw{ tempfile }; |
|
3
|
|
|
|
|
120120
|
|
|
3
|
|
|
|
|
50068
|
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
our $VERSION = '0.15'; |
159
|
|
|
|
|
|
|
my $DEBUG = 0; |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# needed for accessor generation |
162
|
|
|
|
|
|
|
our $AUTOLOAD; |
163
|
|
|
|
|
|
|
my %ATTRIBUTES = (); |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=item new |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
Creates a new Emacs::Run object. |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
Takes a hashref as an argument, with named fields identical |
170
|
|
|
|
|
|
|
to the names of the object attributes. These attributes are: |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=over |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=item emacs_path |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Indicates how to find the emacs program. Defaults to 'emacs', which |
177
|
|
|
|
|
|
|
lets the system (e.g. the shell's PATH environment variable) find the |
178
|
|
|
|
|
|
|
program if it can. If you have multiple emacsen installed in different |
179
|
|
|
|
|
|
|
places and/or under different names, you can choose which one will be |
180
|
|
|
|
|
|
|
used by setting this attribute. |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=item redirector |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
A code that specifies how the default way of handling the |
185
|
|
|
|
|
|
|
standard output and error streams for some methods, such as |
186
|
|
|
|
|
|
|
L, L and L. |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
This may be one of three values: |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=over |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=item stdout_only |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=item stderr_only |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=item all_output (object default -- some methods may differ) |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=back |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
Alternately, one may enter Bourne shell redirection codes using |
201
|
|
|
|
|
|
|
the L. |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=item shell_output_director |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
A Bourne shell redirection code (e.g. '2>&1'). This is an |
206
|
|
|
|
|
|
|
alternative to setting L. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=item before_hook |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
A string inserted into the built-up emacs commands immediately |
211
|
|
|
|
|
|
|
after "--batch", but before any thing else is executed. |
212
|
|
|
|
|
|
|
This is a good place to insert additional invocation options |
213
|
|
|
|
|
|
|
such as "--multibyte" or "--unibyte". See . |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=item load_emacs_init |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
Defaults to 1, if set to a false value, will suppress the use |
218
|
|
|
|
|
|
|
of the user's emacs init file (e.g. "~/.emacs"). |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=item load_site_init |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
Defaults to 1, if set to a false value, will suppress the use |
223
|
|
|
|
|
|
|
of the system "site-start.el" file (which loads before the |
224
|
|
|
|
|
|
|
user's init file). |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=item load_default_init |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
Defaults to 1, if set to a false value, will suppress the use |
229
|
|
|
|
|
|
|
of the system "default.el" file (which loads after the user's |
230
|
|
|
|
|
|
|
init file). |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=item load_no_inits |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
A convenience flag, which may be set to disable all three types of emacs init |
235
|
|
|
|
|
|
|
files in one step. Overrides the other three. |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=item emacs_libs |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
A list of emacs libraries (with or without paths) to be loaded |
240
|
|
|
|
|
|
|
automatically. This is recommended for most uses, though |
241
|
|
|
|
|
|
|
to take full control over how your emacs libraries are handled, |
242
|
|
|
|
|
|
|
see L. |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=item default_priority |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
The global default for how all the emacs libraries should be loaded. |
247
|
|
|
|
|
|
|
Normally this is set to "requested", but it can be set to "needed". |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
A 'requested' library will be silently skipped if it is not available |
250
|
|
|
|
|
|
|
(and any elisp code using it may need to to adapt to it's absense, |
251
|
|
|
|
|
|
|
e.g. by doing 'featurep' checks). |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
A 'needed' file will cause an error to occur if it is not available. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
Note: this error does not occur during object instantiation, but |
256
|
|
|
|
|
|
|
only after a method is called that needs to load the libraries |
257
|
|
|
|
|
|
|
(e.g. L L, L, |
258
|
|
|
|
|
|
|
L, etc). |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
=item lib_data |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
Note: using L is usually preferrable to L. |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
B is the internal representation that is |
265
|
|
|
|
|
|
|
converted into, but the client programmer is provided access to it to |
266
|
|
|
|
|
|
|
cover any unusual needs. |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
The structure of B is an array of arrays of two elements each, |
269
|
|
|
|
|
|
|
the first element is the library name (a string, with or without path), |
270
|
|
|
|
|
|
|
the second element is a hash of library attributes: 'priority' (which can |
271
|
|
|
|
|
|
|
be 'requested' or 'needed') and 'type' (which can be 'file' or 'lib'). |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
Example: |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
$lib_data = [ |
276
|
|
|
|
|
|
|
[ 'dired', { type=>'lib', priority=>'needed' } ], |
277
|
|
|
|
|
|
|
[ '/tmp/my-load-path.el', { type=>'file', priority=>'requested' } ], |
278
|
|
|
|
|
|
|
[ '/tmp/my-elisp.el', { type=>'file', priority=>'needed' } ], |
279
|
|
|
|
|
|
|
]; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
emacs library attributes: |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
=over |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=item priority |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
A 'requested' library will be silently skipped if it is not available, |
288
|
|
|
|
|
|
|
but if a 'needed' file is not available it's regarded as an error condition. |
289
|
|
|
|
|
|
|
The default priority is 'requested', but that can be changed via the |
290
|
|
|
|
|
|
|
L attribute. See L for more |
291
|
|
|
|
|
|
|
details. |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=item type |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
A library of type 'file' should be a filesystem path to a file |
296
|
|
|
|
|
|
|
containing a library of emacs lisp code. A library of type 'lib' is |
297
|
|
|
|
|
|
|
specified by just the basename of the file (sans path or extension), and |
298
|
|
|
|
|
|
|
we will search for it looking in the places specified in the emacs |
299
|
|
|
|
|
|
|
variable load-path. When neither is specified, this module guesses the |
300
|
|
|
|
|
|
|
lib is a file if it looks that way (i.e it has a path and/or extension). |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=back |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
If both B and B are used, the B libraries |
305
|
|
|
|
|
|
|
are loaded first, followed by the B libraries. |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
These attributes are used to pass information to the client programmer, |
308
|
|
|
|
|
|
|
they should be regarded as read-only: |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=over |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=item emacs_version |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
The version number of emacs in use: this is set automatically by the |
315
|
|
|
|
|
|
|
"probe_emacs_version" method during object initialization. |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=item emacs_type |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
The flavor of emacs in use, e.g. 'Gnu Emacs'. Set automatically by |
320
|
|
|
|
|
|
|
the "probe_emacs_version" method during object initialization. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=back |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
There are also a number of object attributes intended largely for |
325
|
|
|
|
|
|
|
internal use. The client programmer has access to these, but |
326
|
|
|
|
|
|
|
is not expected to need it. These are documented in L. |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=back |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
=cut |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# Note: "new" is inherited from Class::Base and |
333
|
|
|
|
|
|
|
# calls the following "init" routine automatically. |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=item init |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
Method that initializes object attributes and then locks them |
338
|
|
|
|
|
|
|
down to prevent accidental creation of new ones. |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
Any class that inherits from this one should have an L of |
341
|
|
|
|
|
|
|
it's own that calls this L. |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=cut |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
sub init { |
346
|
2
|
|
|
2
|
1
|
1009
|
my $self = shift; |
347
|
2
|
|
|
|
|
6
|
my $args = shift; |
348
|
2
|
|
|
|
|
7
|
unlock_keys( %{ $self } ); |
|
2
|
|
|
|
|
22
|
|
349
|
|
|
|
|
|
|
|
350
|
2
|
50
|
|
|
|
25
|
if ($DEBUG) { |
351
|
0
|
|
|
|
|
0
|
$self->debugging(1); |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
# object attributes here, including arguments that become attributes |
355
|
2
|
|
|
|
|
78
|
my @attributes = qw( |
356
|
|
|
|
|
|
|
emacs_path |
357
|
|
|
|
|
|
|
emacs_version |
358
|
|
|
|
|
|
|
emacs_major_version |
359
|
|
|
|
|
|
|
emacs_type |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
load_emacs_init |
362
|
|
|
|
|
|
|
load_site_init |
363
|
|
|
|
|
|
|
load_default_init |
364
|
|
|
|
|
|
|
load_no_inits |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
emacs_libs |
367
|
|
|
|
|
|
|
lib_data |
368
|
|
|
|
|
|
|
lib_data_initial |
369
|
|
|
|
|
|
|
default_priority |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
before_hook |
372
|
|
|
|
|
|
|
ec_lib_loader |
373
|
|
|
|
|
|
|
shell_output_director |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
redirector |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
message_log |
378
|
|
|
|
|
|
|
); |
379
|
|
|
|
|
|
|
|
380
|
2
|
|
|
|
|
7
|
foreach my $field (@attributes) { |
381
|
34
|
|
|
|
|
49
|
$ATTRIBUTES{ $field } = 1; |
382
|
34
|
|
|
|
|
108
|
$self->{ $field } = $args->{ $field }; |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
|
385
|
2
|
50
|
33
|
|
|
18
|
if( $self->{ redirector } && $self->{ shell_output_director } ) { |
386
|
0
|
|
|
|
|
0
|
carp "redirector takes precedence: shell_output_director setting ignored."; |
387
|
|
|
|
|
|
|
} |
388
|
2
|
50
|
|
|
|
17
|
if( $self->{ redirector } ) { |
|
|
50
|
|
|
|
|
|
389
|
0
|
|
|
|
|
0
|
$self->{ shell_output_director } = $self->redirector_to_sod( $self->redirector ); |
390
|
|
|
|
|
|
|
} elsif ( $self->{ shell_output_director } ) { |
391
|
0
|
|
|
|
|
0
|
$self->{ redirector } = ''; # shouldn't matter now, in any case |
392
|
|
|
|
|
|
|
} else { |
393
|
|
|
|
|
|
|
# by default, we intermix STDOUT and STDERR |
394
|
2
|
|
|
|
|
5
|
$self->{ shell_output_director } = '2>&1'; |
395
|
2
|
|
|
|
|
4
|
$self->{ redirector } = 'all_output'; # redundant? what the hell. |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
# Define attributes (apply defaults, etc) |
399
|
2
|
|
|
|
|
4
|
$self->{ec_lib_loader} = ''; |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# If we weren't given a path, let the $PATH sort it out |
402
|
2
|
|
100
|
|
|
13
|
$self->{ emacs_path } ||= 'emacs'; |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# Determine the emacs version (if we haven't been told already - but why override TODO?) |
405
|
2
|
|
33
|
|
|
16
|
$self->{ emacs_version } ||= $self->probe_emacs_version; |
406
|
2
|
50
|
|
|
|
23
|
unless( $self->{ emacs_version } ) { # if emacs is not found, just bail |
407
|
2
|
|
|
|
|
160
|
return; |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
# By default, we like to load all init files |
411
|
0
|
0
|
|
|
|
0
|
$self->{load_emacs_init} = 1 unless defined( $self->{load_emacs_init} ); |
412
|
0
|
0
|
|
|
|
0
|
$self->{load_site_init} = 1 unless defined( $self->{load_site_init} ); |
413
|
0
|
0
|
|
|
|
0
|
$self->{load_default_init} = 1 unless defined( $self->{load_default_init} ); |
414
|
|
|
|
|
|
|
|
415
|
0
|
0
|
|
|
|
0
|
if( $self->{load_no_inits} ) { # ... but we make it easy to suppress all of them, too. |
416
|
0
|
|
|
|
|
0
|
$self->{load_emacs_init} = 0; |
417
|
0
|
|
|
|
|
0
|
$self->{load_site_init} = 0; |
418
|
0
|
|
|
|
|
0
|
$self->{load_default_init} = 0; |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
|
421
|
0
|
|
0
|
|
|
0
|
$self->{ before_hook } ||= ''; |
422
|
0
|
0
|
|
|
|
0
|
if($self->{load_no_inits} ) { |
423
|
0
|
|
|
|
|
0
|
$self->append_to_before_hook( ' -Q ' ); |
424
|
|
|
|
|
|
|
} |
425
|
|
|
|
|
|
|
|
426
|
0
|
|
0
|
|
|
0
|
$self->{ default_priority } ||= 'requested'; |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
# preserving any given lib_data in the event of a need to reset. |
429
|
0
|
|
|
|
|
0
|
$self->{lib_data_initial} = $self->{ lib_data }; |
430
|
|
|
|
|
|
|
|
431
|
0
|
0
|
|
|
|
0
|
if( defined( my $emacs_libs = $self->{ emacs_libs } ) ) { |
432
|
0
|
|
|
|
|
0
|
$self->process_emacs_libs_addition( $emacs_libs ); |
433
|
|
|
|
|
|
|
} else { |
434
|
|
|
|
|
|
|
# called indirectly by process_emacs_libs_addition. |
435
|
|
|
|
|
|
|
# no point in doing it again, *unless* no emacs_libs |
436
|
0
|
|
|
|
|
0
|
$self->set_up_ec_lib_loader; |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
0
|
|
|
|
|
0
|
lock_keys( %{ $self } ); |
|
0
|
|
|
|
|
0
|
|
440
|
0
|
|
|
|
|
0
|
return $self; |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
=back |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
=head2 Simple Emacs Invocations |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
Some simple methods for obtaining information from your emacs |
449
|
|
|
|
|
|
|
installation. |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
These methods default to returning STDOUT, suppressing anything |
452
|
|
|
|
|
|
|
sent to STDERR. This behavior can be overridden: see |
453
|
|
|
|
|
|
|
L. |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
=over |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
=item eval_function |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
Given the name of an emacs function, this runs the function and |
460
|
|
|
|
|
|
|
returns the value from emacs (when started with the the .emacs |
461
|
|
|
|
|
|
|
located in $HOME, if one is found). After the function name, an |
462
|
|
|
|
|
|
|
optional array reference may be supplied to pass through a list |
463
|
|
|
|
|
|
|
of simple arguments (limited to strings) to the elisp function. |
464
|
|
|
|
|
|
|
And further, an optional hash reference may follow that to |
465
|
|
|
|
|
|
|
specify options to the "eval_function" method. |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
By default the returned output is STDOUT only but this behavior |
468
|
|
|
|
|
|
|
can be overridden: See L. |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
As with L, this uses the emacs 'print' function |
471
|
|
|
|
|
|
|
internally. |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
Examples: |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
my $name = $er->eval_function( 'user-full-name' ); |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
$er->eval_function( 'extract-doctrings-generate-html-for-elisp-file', |
478
|
|
|
|
|
|
|
[ "$input_elisp_file", |
479
|
|
|
|
|
|
|
"$output_file", |
480
|
|
|
|
|
|
|
"The extracted docstrings" ] ); |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
=cut |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
sub eval_function { |
485
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
486
|
0
|
|
|
|
|
0
|
my $funcname = shift; |
487
|
0
|
|
|
|
|
0
|
my $arg2 = shift; |
488
|
0
|
|
|
|
|
0
|
my $subname = ( caller(0) )[3]; |
489
|
|
|
|
|
|
|
|
490
|
0
|
|
|
|
|
0
|
my $devnull = File::Spec->devnull(); |
491
|
|
|
|
|
|
|
|
492
|
0
|
|
|
|
|
0
|
my ($passthroughs, $opts, $passthru); |
493
|
0
|
0
|
|
|
|
0
|
if (ref( $arg2 ) eq 'ARRAY') { |
|
|
0
|
|
|
|
|
|
494
|
0
|
|
|
|
|
0
|
$passthroughs = $arg2; |
495
|
0
|
|
|
|
|
0
|
$passthru = join " ", map{ qq{"$_"} } @{ $passthroughs }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
496
|
0
|
|
|
|
|
0
|
$opts = shift; |
497
|
|
|
|
|
|
|
} elsif (ref( $arg2 ) eq 'HASH') { |
498
|
0
|
|
|
|
|
0
|
$opts = $arg2; |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
|
501
|
0
|
|
0
|
|
|
0
|
my $redirector = $opts->{ redirector } || "stdout_only"; |
502
|
|
|
|
|
|
|
my $sod = |
503
|
|
|
|
|
|
|
$opts->{ shell_output_director } || |
504
|
0
|
|
0
|
|
|
0
|
$self->redirector_to_sod( $redirector ) || |
505
|
|
|
|
|
|
|
"2>$devnull"; |
506
|
|
|
|
|
|
|
|
507
|
0
|
|
|
|
|
0
|
my $elisp; |
508
|
0
|
0
|
|
|
|
0
|
if( $passthru ) { |
509
|
0
|
|
|
|
|
0
|
$elisp = qq{ (print ($funcname $passthru)) }; |
510
|
|
|
|
|
|
|
} else { |
511
|
0
|
|
|
|
|
0
|
$elisp = qq{ (print ($funcname)) }; |
512
|
|
|
|
|
|
|
} |
513
|
|
|
|
|
|
|
|
514
|
0
|
|
|
|
|
0
|
my $return = $self->eval_elisp( $elisp, { |
515
|
|
|
|
|
|
|
shell_output_director => $sod, |
516
|
|
|
|
|
|
|
} ); |
517
|
0
|
|
|
|
|
0
|
return $return; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=item get_variable |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
Given the name of an emacs variable, returns the value from |
523
|
|
|
|
|
|
|
emacs (when started with the the .emacs located in $HOME, |
524
|
|
|
|
|
|
|
if one is found), |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
Internally, this uses the emacs 'print' function, which can |
527
|
|
|
|
|
|
|
handle variables containing complex data types, but the |
528
|
|
|
|
|
|
|
return value will be a "printed representation" that may |
529
|
|
|
|
|
|
|
make more sense to emacs than to perl code. For example, |
530
|
|
|
|
|
|
|
the "load-path" variable might look like: |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
("/home/grunt/lib" "/usr/lib/emacs/site-lisp" "/home/xtra/lib") |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
See L below for a more perl-friendly way of doing this. |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
Ignores redirector/shell_output_director. |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
=cut |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
sub get_variable { |
541
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
542
|
0
|
|
|
|
|
0
|
my $varname = shift; |
543
|
0
|
|
|
|
|
0
|
my $opts = shift; |
544
|
0
|
|
|
|
|
0
|
my $devnull = File::Spec->devnull(); |
545
|
|
|
|
|
|
|
|
546
|
0
|
|
|
|
|
0
|
my $redirector = 'stdout_only'; |
547
|
0
|
|
|
|
|
0
|
my $sod = $self->redirector_to_sod( $redirector ); |
548
|
|
|
|
|
|
|
|
549
|
0
|
|
|
|
|
0
|
my $subname = ( caller(0) )[3]; |
550
|
0
|
|
|
|
|
0
|
my $elisp = qq{ (print $varname) }; |
551
|
0
|
|
|
|
|
0
|
my $return = $self->eval_elisp( $elisp, { |
552
|
|
|
|
|
|
|
shell_output_director => $sod, |
553
|
|
|
|
|
|
|
} ); |
554
|
0
|
|
|
|
|
0
|
return $return; |
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
=item get_load_path |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
Returns the load-path from emacs (by default, using the |
560
|
|
|
|
|
|
|
user's .emacs, if it can be found) as a reference to a perl array. |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
Changing the $HOME environment variable before running this method |
563
|
|
|
|
|
|
|
results in loading the .emacs file located in the new $HOME. |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
Ignores redirector/shell_output_director. |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
=cut |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
sub get_load_path { |
570
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
571
|
0
|
|
|
|
|
0
|
my $opts = shift; |
572
|
0
|
|
|
|
|
0
|
my $devnull = File::Spec->devnull(); |
573
|
|
|
|
|
|
|
|
574
|
0
|
|
|
|
|
0
|
my $redirector = 'stdout_only'; |
575
|
0
|
|
|
|
|
0
|
my $sod = $self->redirector_to_sod( $redirector ); |
576
|
|
|
|
|
|
|
|
577
|
0
|
|
|
|
|
0
|
my $elisp = q{ (print (mapconcat 'identity load-path "\n")) }; |
578
|
|
|
|
|
|
|
|
579
|
0
|
|
|
|
|
0
|
my $return = $self->eval_elisp( $elisp, { |
580
|
|
|
|
|
|
|
shell_output_director => $sod, |
581
|
|
|
|
|
|
|
} ); |
582
|
0
|
|
|
|
|
0
|
my @load_path = split /\n/, $return; |
583
|
0
|
|
|
|
|
0
|
\@load_path; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
=item probe_for_option_no_splash |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
Looks for the emacs command line option "--no-splash", returning true (1) |
591
|
|
|
|
|
|
|
if it exists, and false (0) otherwise. |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
Ignores redirector/shell_output_director. |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
=cut |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
# earlier versions called this "no_splash_p" |
598
|
|
|
|
|
|
|
sub probe_for_option_no_splash { |
599
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
600
|
0
|
|
|
|
|
0
|
my $subname = ( caller(0) )[3]; |
601
|
|
|
|
|
|
|
|
602
|
0
|
|
|
|
|
0
|
my $emacs = $self->emacs_path; |
603
|
0
|
|
|
|
|
0
|
my $before_hook = $self->before_hook; |
604
|
0
|
|
|
|
|
0
|
$before_hook .= ' --no-splash '; |
605
|
|
|
|
|
|
|
|
606
|
0
|
0
|
|
|
|
0
|
if ( $self->emacs_type eq 'XEmacs' ) { |
607
|
0
|
|
|
|
|
0
|
return 0; # xemacs has no --no-splash |
608
|
|
|
|
|
|
|
} |
609
|
|
|
|
|
|
|
|
610
|
0
|
|
|
|
|
0
|
my $sod = '2>&1'; |
611
|
|
|
|
|
|
|
|
612
|
0
|
|
|
|
|
0
|
my $cmd = qq{ $emacs --batch $before_hook $sod }; |
613
|
0
|
|
|
|
|
0
|
$self->debug("$subname: cmd: $cmd\n"); |
614
|
0
|
|
|
|
|
0
|
my $retval = qx{ $cmd }; |
615
|
0
|
|
|
|
|
0
|
$retval = $self->clean_return_value( $retval ); |
616
|
|
|
|
|
|
|
|
617
|
0
|
|
0
|
|
|
0
|
my $last_line = ( split /\n/, $retval )[-1] || ''; |
618
|
|
|
|
|
|
|
|
619
|
0
|
|
|
|
|
0
|
$self->debug( "$subname retval:\n===\n$retval\n===\n" ); |
620
|
|
|
|
|
|
|
|
621
|
0
|
0
|
|
|
|
0
|
if( $retval =~ m{ Unknown \s+ option \s+ .*? --no-splash }xms ) { |
622
|
0
|
|
|
|
|
0
|
return 0; |
623
|
|
|
|
|
|
|
} else { |
624
|
0
|
|
|
|
|
0
|
return 1; |
625
|
|
|
|
|
|
|
} |
626
|
|
|
|
|
|
|
} |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
=back |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
=head2 Running Elisp |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
These are general methods that run pieces of emacs lisp code. |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
The detailed behavior of these methods have a number of things |
637
|
|
|
|
|
|
|
in common: |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
By default the method first loads the user's initialization |
640
|
|
|
|
|
|
|
file ("$HOME/.emacs") if it can be found. It will also try to |
641
|
|
|
|
|
|
|
load the libraries listed in the L and/or |
642
|
|
|
|
|
|
|
L attributes. |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
There are object attribute settings that can be used to suppress |
645
|
|
|
|
|
|
|
loading any of the various init files. See L for the full |
646
|
|
|
|
|
|
|
list. In particular, if the L attribute has |
647
|
|
|
|
|
|
|
been turned off, it will not try to load the .emacs file. |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
Unless specified otherwise, the methods return the |
650
|
|
|
|
|
|
|
output from the elisp code with STDOUT and STDERR |
651
|
|
|
|
|
|
|
mixed together, though this behavior can be overridden. |
652
|
|
|
|
|
|
|
See L. |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
(The advantage of intermixing STDOUT and STDERR is that the |
655
|
|
|
|
|
|
|
emacs functions 'message' as well as 'print' both may be used |
656
|
|
|
|
|
|
|
for interesting output. The disadvantage is that you may have |
657
|
|
|
|
|
|
|
many inane messages from emacs sent to STDERR such as 'Loading |
658
|
|
|
|
|
|
|
library so-and-so') |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
=over |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
=item eval_elisp |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
Given a string containing a chunk of elisp code this method runs |
665
|
|
|
|
|
|
|
it by invoking emacs in batch mode. |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
Example: |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
my $result = $er->eval_elisp( '(print (+ 2 2))' ); |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
=cut |
672
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
sub eval_elisp { |
674
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
675
|
0
|
|
|
|
|
0
|
my $elisp = shift; |
676
|
0
|
|
|
|
|
0
|
my $opts = shift; |
677
|
0
|
|
|
|
|
0
|
my $subname = ( caller(0) )[3]; |
678
|
|
|
|
|
|
|
|
679
|
0
|
|
0
|
|
|
0
|
my $redirector = $opts->{ redirector } || $self->redirector; |
680
|
|
|
|
|
|
|
my $sod = |
681
|
|
|
|
|
|
|
$opts->{ shell_output_director } || |
682
|
0
|
|
0
|
|
|
0
|
$self->redirector_to_sod( $opts->{ redirector } ) || |
683
|
|
|
|
|
|
|
$self->shell_output_director || |
684
|
|
|
|
|
|
|
$self->redirector_to_sod( $self->redirector ); |
685
|
|
|
|
|
|
|
|
686
|
0
|
|
|
|
|
0
|
$elisp = $self->quote_elisp( $self->progn_wrapper( $elisp )); |
687
|
|
|
|
|
|
|
|
688
|
0
|
|
|
|
|
0
|
my $emacs = $self->emacs_path; |
689
|
0
|
|
|
|
|
0
|
my $before_hook = $self->before_hook; |
690
|
|
|
|
|
|
|
|
691
|
0
|
|
|
|
|
0
|
my $ec_head = qq{ $emacs --batch $before_hook }; |
692
|
0
|
|
|
|
|
0
|
my $ec_tail = qq{ --eval "$elisp" }; |
693
|
0
|
|
|
|
|
0
|
my $ec_lib_loader = $self->set_up_ec_lib_loader; |
694
|
|
|
|
|
|
|
|
695
|
0
|
|
|
|
|
0
|
my $cmd = "$ec_head $ec_lib_loader $ec_tail $sod"; |
696
|
0
|
|
|
|
|
0
|
$self->debug("$subname: cmd:\n $cmd\n"); |
697
|
|
|
|
|
|
|
|
698
|
0
|
|
|
|
|
0
|
my $retval = qx{ $cmd }; |
699
|
0
|
|
|
|
|
0
|
$retval = $self->clean_return_value( $retval ); |
700
|
0
|
|
|
|
|
0
|
$self->debug( "$subname retval:\n===\n$retval\n===\n" ); |
701
|
|
|
|
|
|
|
|
702
|
0
|
|
|
|
|
0
|
return $retval; |
703
|
|
|
|
|
|
|
} |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
=item run_elisp_on_file |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
Given a file name, and some emacs lisp code (which presumably |
708
|
|
|
|
|
|
|
modifies the current buffer), this method opens the file, runs |
709
|
|
|
|
|
|
|
the code on it, and then saves the file. |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
Returns whatever value the elisp returns. |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
Example usage: |
714
|
|
|
|
|
|
|
$self->run_elisp_on_file( $filename, $elisp ); |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
=cut |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
sub run_elisp_on_file { |
719
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
720
|
0
|
|
|
|
|
0
|
my $filename = shift; |
721
|
0
|
|
|
|
|
0
|
my $elisp = shift; |
722
|
0
|
|
|
|
|
0
|
my $opts = shift; |
723
|
0
|
|
|
|
|
0
|
my $subname = ( caller(0) )[3]; |
724
|
|
|
|
|
|
|
|
725
|
0
|
|
0
|
|
|
0
|
my $redirector = $opts->{ redirector } || $self->redirector; |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
my $sod = |
728
|
|
|
|
|
|
|
( $opts->{ shell_output_director } ) || |
729
|
0
|
|
0
|
|
|
0
|
( $self->redirector_to_sod( $opts->{ redirector } ) ) || |
730
|
|
|
|
|
|
|
( $self->shell_output_director ) || |
731
|
|
|
|
|
|
|
( $self->redirector_to_sod( $self->redirector ) ); |
732
|
|
|
|
|
|
|
|
733
|
0
|
|
|
|
|
0
|
$elisp = $self->quote_elisp( $elisp ); |
734
|
|
|
|
|
|
|
|
735
|
0
|
|
|
|
|
0
|
my $emacs = $self->emacs_path; |
736
|
0
|
|
|
|
|
0
|
my $before_hook = $self->before_hook; |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
# Covering a stupidity with some versions of gnu emacs 21: "--no-splash" |
739
|
|
|
|
|
|
|
# to suppress an inane splash screen. |
740
|
0
|
0
|
0
|
|
|
0
|
if ( $self->emacs_major_version eq '21' && |
|
|
|
0
|
|
|
|
|
741
|
|
|
|
|
|
|
$self->emacs_type eq 'GNU Emacs' && |
742
|
|
|
|
|
|
|
$self->probe_for_option_no_splash ) { |
743
|
0
|
|
|
|
|
0
|
$before_hook .= ' --no-splash '; |
744
|
|
|
|
|
|
|
} |
745
|
|
|
|
|
|
|
|
746
|
0
|
|
|
|
|
0
|
my $ec_head = qq{ $emacs --batch $before_hook --file='$filename' }; |
747
|
0
|
|
|
|
|
0
|
my $ec_tail = qq{ --eval "$elisp" -f save-buffer }; |
748
|
0
|
|
|
|
|
0
|
my $ec_lib_loader = $self->ec_lib_loader; |
749
|
|
|
|
|
|
|
|
750
|
0
|
|
|
|
|
0
|
my $cmd = "$ec_head $ec_lib_loader $ec_tail $sod"; |
751
|
0
|
|
|
|
|
0
|
$self->debug("$subname: cmd: $cmd\n"); |
752
|
|
|
|
|
|
|
|
753
|
0
|
|
|
|
|
0
|
my $retval = qx{ $cmd }; |
754
|
0
|
|
|
|
|
0
|
$retval = $self->clean_return_value( $retval ); |
755
|
0
|
|
|
|
|
0
|
$self->debug( "$subname retval:\n===\n$retval\n===\n" ); |
756
|
|
|
|
|
|
|
|
757
|
0
|
|
|
|
|
0
|
return $retval; |
758
|
|
|
|
|
|
|
} |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
=item eval_elisp_full_emacs |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
Runs the given chunk(s) of elisp using a temporarily launched |
763
|
|
|
|
|
|
|
full scale emacs window (does not work via "--batch" mode). |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
Returns an array reference of lines of output. |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
Of necessity, this emacs sub-process must communicate through a |
768
|
|
|
|
|
|
|
file (similar to "run_elisp_on_file"), so the elisp run by this |
769
|
|
|
|
|
|
|
routine should be designed to output to the current buffer |
770
|
|
|
|
|
|
|
(e.g. via "insert" calls). |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
Any elisp functions such as "message" and "print" will have no |
773
|
|
|
|
|
|
|
direct effect on output, and neither the or |
774
|
|
|
|
|
|
|
have any effect here. |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
As an option, a separate chunk of initialization elisp may also be |
777
|
|
|
|
|
|
|
passed in: it will be run before the output file buffer is |
778
|
|
|
|
|
|
|
opened, and hence any modification it makes to the current buffer |
779
|
|
|
|
|
|
|
will be ignored. |
780
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
If the "output_filename" is not supplied, a temporary file will |
782
|
|
|
|
|
|
|
be created and deleted afterwards. If the name is supplied, the |
783
|
|
|
|
|
|
|
output file will be still exist afterwards (but note: any existing |
784
|
|
|
|
|
|
|
contents will be over-written). |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
The current buffer is saved at the end of the processing (so |
787
|
|
|
|
|
|
|
there's no need to include a "save-buffer" call in the elisp). |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
All arguments are passed into this method via a hashref of |
790
|
|
|
|
|
|
|
options. These are: |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
elisp_initialize |
793
|
|
|
|
|
|
|
output_file |
794
|
|
|
|
|
|
|
elisp |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
Note that this last "option" is not optional: you need to supply |
797
|
|
|
|
|
|
|
some "elisp" if you want anything to happen. |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
Example use: |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
my $er = Emacs::Run->new({ |
802
|
|
|
|
|
|
|
load_no_inits = 1, |
803
|
|
|
|
|
|
|
emacs_libs => [ '~/lib/my-elisp.el', |
804
|
|
|
|
|
|
|
'/usr/lib/site-emacs/stuff.el' ], |
805
|
|
|
|
|
|
|
}); |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
# Using just the 'elisp' argument: |
808
|
|
|
|
|
|
|
my $elisp = |
809
|
|
|
|
|
|
|
qq{ (insert-file "$input_file") |
810
|
|
|
|
|
|
|
(downcase-region (point-min) (point-max)) |
811
|
|
|
|
|
|
|
}; |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
my $output = |
814
|
|
|
|
|
|
|
$er->eval_elisp_full_emacs( { |
815
|
|
|
|
|
|
|
elisp => $elisp, |
816
|
|
|
|
|
|
|
} |
817
|
|
|
|
|
|
|
); |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
# Using all options: |
820
|
|
|
|
|
|
|
my $output = |
821
|
|
|
|
|
|
|
$er->eval_elisp_full_emacs( { |
822
|
|
|
|
|
|
|
elisp_initialize => $elisp_initialize, |
823
|
|
|
|
|
|
|
output_file => $output_file, |
824
|
|
|
|
|
|
|
elisp => $elisp, |
825
|
|
|
|
|
|
|
message_log => '/tmp/message.log', |
826
|
|
|
|
|
|
|
} |
827
|
|
|
|
|
|
|
); |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
This method only uses some of the usual Emacs::Run framework: |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
The three individual init settings flags have no effect on this |
832
|
|
|
|
|
|
|
method ("load_emacs_init", "load_site_init", "load_default_init"). |
833
|
|
|
|
|
|
|
If "load_no_inits" is set, the emacs init files will be ignored |
834
|
|
|
|
|
|
|
(via "-q") unless, of course, they're passed in manually in the |
835
|
|
|
|
|
|
|
"emacs_libs" array reference. |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
Adding libraries to emacs_libs will not automatically add their |
838
|
|
|
|
|
|
|
locations to the load-path (because the "ec_lib_loader" system is |
839
|
|
|
|
|
|
|
not in use here). |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
Ignores redirector/shell_output_director. |
842
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
If the option "message_log" contains the name of a log file |
844
|
|
|
|
|
|
|
the emacs '*Messages*' buffer will be appended to it. |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
=cut |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
sub eval_elisp_full_emacs { |
849
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
850
|
0
|
|
|
|
|
0
|
my $opts = shift; |
851
|
0
|
|
|
|
|
0
|
my $subname = ( caller(0) )[3]; |
852
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
# unpack options |
854
|
|
|
|
|
|
|
# my $elisp = $opts->{ elisp }; |
855
|
0
|
|
|
|
|
0
|
my $elisp_initialize = $self->progn_wrapper( $opts->{ elisp_initialize } ); |
856
|
0
|
|
|
|
|
0
|
my $elisp = $self->progn_wrapper( $opts->{ elisp } ); |
857
|
0
|
|
|
|
|
0
|
my $output_file = $opts->{ output_file }; |
858
|
|
|
|
|
|
|
|
859
|
0
|
|
0
|
|
|
0
|
my $message_log = $opts->{ message_log } || $self->message_log; |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
# if $output_file is blank, need to pick a temp file to use. |
862
|
0
|
0
|
|
|
|
0
|
unless( $output_file ) { |
863
|
0
|
|
|
|
|
0
|
my $fh; |
864
|
0
|
|
|
|
|
0
|
my $unlink = not( $DEBUG ); |
865
|
0
|
|
|
|
|
0
|
($fh, $output_file) = |
866
|
|
|
|
|
|
|
tempfile( "emacs_run_eval_elisp_full_emacs-$$-XXXX", |
867
|
|
|
|
|
|
|
SUFFIX => '.txt', |
868
|
|
|
|
|
|
|
UNLINK => $unlink ); |
869
|
0
|
|
|
|
|
0
|
close ($fh); # after it's written by the subprocess, we will read this file |
870
|
|
|
|
|
|
|
} |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
# Have to do this to ensure that exit condition works |
873
|
0
|
0
|
|
|
|
0
|
unlink( $output_file ) if -e $output_file; |
874
|
|
|
|
|
|
|
|
875
|
0
|
|
|
|
|
0
|
my $emacs = $self->emacs_path; |
876
|
0
|
|
|
|
|
0
|
my $before_hook = $self->before_hook; |
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
# need "--no-splash" for some versions of emacs |
879
|
0
|
0
|
0
|
|
|
0
|
if ( $self->emacs_major_version eq '21' && |
|
|
|
0
|
|
|
|
|
880
|
|
|
|
|
|
|
$self->emacs_type eq 'GNU Emacs' && |
881
|
|
|
|
|
|
|
$self->probe_for_option_no_splash ) { |
882
|
0
|
|
|
|
|
0
|
$before_hook .= ' --no-splash '; |
883
|
|
|
|
|
|
|
} |
884
|
|
|
|
|
|
|
|
885
|
0
|
0
|
|
|
|
0
|
my $elisp_log_messages = $self->progn_wrapper( |
886
|
|
|
|
|
|
|
$message_log ? |
887
|
|
|
|
|
|
|
qq{ |
888
|
|
|
|
|
|
|
(find-file "$message_log") |
889
|
|
|
|
|
|
|
(insert (format "\n $0 logging *Messages* - %s\n" (current-time-string))) |
890
|
|
|
|
|
|
|
(goto-char (point-max)) |
891
|
|
|
|
|
|
|
(insert-buffer "*Messages*") |
892
|
|
|
|
|
|
|
} : '' |
893
|
|
|
|
|
|
|
); |
894
|
0
|
0
|
|
|
|
0
|
($DEBUG) && print STDERR "\n$elisp_log_messages\n\n"; |
895
|
|
|
|
|
|
|
|
896
|
0
|
|
|
|
|
0
|
my $output_buffer = basename( $output_file ); |
897
|
0
|
|
|
|
|
0
|
my $elisp_back_to_output = |
898
|
|
|
|
|
|
|
qq{ |
899
|
|
|
|
|
|
|
(switch-to-buffer "$output_buffer") |
900
|
|
|
|
|
|
|
}; |
901
|
0
|
0
|
|
|
|
0
|
($DEBUG) && print STDERR "\n", $elisp_back_to_output, "\n\n"; |
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
# Build up the command arguments |
904
|
0
|
|
|
|
|
0
|
my @cmd; |
905
|
0
|
|
|
|
|
0
|
push @cmd, ( "emacs_from_" . "$$" ); # just the process label, not the binary |
906
|
|
|
|
|
|
|
|
907
|
0
|
0
|
|
|
|
0
|
push @cmd, @{ $self->parse_ec_string( $before_hook ) } if $before_hook; |
|
0
|
|
|
|
|
0
|
|
908
|
|
|
|
|
|
|
|
909
|
0
|
|
|
|
|
0
|
foreach my $lib ( @{ $self->emacs_libs } ) { |
|
0
|
|
|
|
|
0
|
|
910
|
0
|
0
|
|
|
|
0
|
push @cmd, ( "-l", "$lib" ) if $lib; |
911
|
|
|
|
|
|
|
} |
912
|
|
|
|
|
|
|
|
913
|
0
|
0
|
|
|
|
0
|
push @cmd, ( "--eval", "$elisp_initialize" ) if $elisp_initialize; |
914
|
0
|
|
|
|
|
0
|
push @cmd, ( "--file", "$output_file" ); |
915
|
0
|
|
|
|
|
0
|
push @cmd, ( "--eval", "$elisp" ); |
916
|
|
|
|
|
|
|
|
917
|
0
|
0
|
|
|
|
0
|
if ($message_log) { |
918
|
0
|
|
|
|
|
0
|
push @cmd, ( "--eval", "$elisp_log_messages" ); |
919
|
0
|
|
|
|
|
0
|
push @cmd, ( "-f", "save-buffer" ); |
920
|
|
|
|
|
|
|
} |
921
|
|
|
|
|
|
|
|
922
|
0
|
|
|
|
|
0
|
push @cmd, ( "--eval", "$elisp_back_to_output" ); |
923
|
0
|
|
|
|
|
0
|
push @cmd, ( "-f", "save-buffer" ); |
924
|
|
|
|
|
|
|
|
925
|
0
|
|
|
|
|
0
|
$self->debug("$subname: cmd: " . Dumper( \@cmd ) . "\n"); |
926
|
|
|
|
|
|
|
|
927
|
0
|
0
|
|
|
|
0
|
if ( my $pid = fork ) { |
928
|
|
|
|
|
|
|
# this is parent code |
929
|
0
|
0
|
|
|
|
0
|
($DEBUG) && print STDERR "I'm the parent, the child pid is $pid\n"; |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
# kill the child emacs when it's finished |
932
|
0
|
|
|
|
|
0
|
LOOP: while(1) { # TODO needs to time out (what if *nothing* is written?) |
933
|
0
|
0
|
|
|
|
0
|
if ( $self->full_emacs_done ({ output_file => $output_file, |
934
|
|
|
|
|
|
|
pid => $pid }) ){ |
935
|
0
|
|
|
|
|
0
|
sleep 1; # a little time for things to settle down (paranoia) |
936
|
0
|
|
|
|
|
0
|
my $status = |
937
|
|
|
|
|
|
|
kill 1, $pid; |
938
|
0
|
0
|
|
|
|
0
|
($DEBUG) && print STDERR "Tried to kill (1) pid $pid, status: $status \n"; |
939
|
0
|
|
|
|
|
0
|
last LOOP; |
940
|
|
|
|
|
|
|
} |
941
|
|
|
|
|
|
|
} |
942
|
|
|
|
|
|
|
} else { |
943
|
|
|
|
|
|
|
# this is child code |
944
|
0
|
0
|
|
|
|
0
|
die "cannot fork: $!" unless defined $pid; |
945
|
|
|
|
|
|
|
|
946
|
0
|
0
|
|
|
|
0
|
($DEBUG) && print STDERR "This is the child, about to exec:\n"; |
947
|
0
|
|
|
|
|
0
|
exec { $emacs } @cmd; |
|
0
|
|
|
|
|
0
|
|
948
|
|
|
|
|
|
|
} |
949
|
|
|
|
|
|
|
|
950
|
0
|
0
|
|
|
|
0
|
open my $fh, '<', $output_file or die "$!"; |
951
|
0
|
|
|
|
|
0
|
my @result = map{ chomp($_); s{\r$}{}xms; $_ } <$fh>; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
952
|
|
|
|
|
|
|
# Note: stripping CRs is a hack to deal with some windows-oriented .emacs |
953
|
0
|
|
|
|
|
0
|
return \@result; |
954
|
|
|
|
|
|
|
} |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
=item full_emacs_done |
958
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
Internally used routine. |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
When it looks as though the child process run by |
962
|
|
|
|
|
|
|
eval_elisp_full_emacs is finished, this returns true. |
963
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
At present, this just watches to see when the output_file |
965
|
|
|
|
|
|
|
has been written. |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
=cut |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
### TODO - would be better to watch the process somehow and determine when it's idle. |
970
|
|
|
|
|
|
|
sub full_emacs_done { |
971
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
972
|
0
|
|
|
|
|
0
|
my $opts = shift; |
973
|
|
|
|
|
|
|
|
974
|
0
|
|
|
|
|
0
|
my $pid = $opts->{ pid }; |
975
|
0
|
|
|
|
|
0
|
my $output_file = $opts->{ output_file }; |
976
|
|
|
|
|
|
|
|
977
|
0
|
|
|
|
|
0
|
my $cutoff = 0; # could increase, if this seems flaky |
978
|
0
|
0
|
0
|
|
|
0
|
if ( (-e $output_file) && ( (-s $output_file) > $cutoff ) ) { |
979
|
0
|
|
|
|
|
0
|
return 1; |
980
|
|
|
|
|
|
|
} else { |
981
|
0
|
|
|
|
|
0
|
return 0; |
982
|
|
|
|
|
|
|
} |
983
|
|
|
|
|
|
|
} |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
=back |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
=head1 INTERNAL METHODS |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
The following methods are intended primarily for internal use. |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
Note: the common "leading underscore" naming convention is not used here. |
993
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
=head2 Utility Methods |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
=over |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
=item quote_elisp |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
Routine to quote elisp code before feeding it into an emacs batch |
1001
|
|
|
|
|
|
|
shell command. Used internally by methods such as L. |
1002
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
This just adds a single backslash to all the double-quote characters |
1004
|
|
|
|
|
|
|
(essentially an empirically determined algorithm, i.e. hack). |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
Example usage: |
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
$elisp = $self->quote_elisp( $elisp ); |
1009
|
|
|
|
|
|
|
$emacs_cmd = qq{ emacs --batch --eval "$elisp" 2>&1 }; |
1010
|
|
|
|
|
|
|
my $return = qx{ $emacs_cmd }; |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
=cut |
1013
|
|
|
|
|
|
|
|
1014
|
|
|
|
|
|
|
sub quote_elisp { |
1015
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1016
|
0
|
|
|
|
|
0
|
my $elisp = shift; |
1017
|
|
|
|
|
|
|
|
1018
|
0
|
|
|
|
|
0
|
$elisp =~ s{"}{\\"}xmsg; # add one backwhack to the double-quotes |
1019
|
0
|
|
|
|
|
0
|
return $elisp; |
1020
|
|
|
|
|
|
|
} |
1021
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
=item progn_wrapper |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
Takes a chunk of elisp, and adds a "progn" around it, to help |
1026
|
|
|
|
|
|
|
make multi-line chunks of elisp Just Work. |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
=cut |
1029
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
sub progn_wrapper { |
1031
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1032
|
0
|
|
|
|
|
0
|
my $elisp = shift; |
1033
|
|
|
|
|
|
|
|
1034
|
0
|
0
|
|
|
|
0
|
$elisp = "(progn $elisp )" if $elisp; |
1035
|
0
|
|
|
|
|
0
|
return $elisp; |
1036
|
|
|
|
|
|
|
} |
1037
|
|
|
|
|
|
|
|
1038
|
|
|
|
|
|
|
=item parse_ec_string |
1039
|
|
|
|
|
|
|
|
1040
|
|
|
|
|
|
|
Takes a chunk of emacs command-line invocation in string form |
1041
|
|
|
|
|
|
|
and converts it to a list form (suitable for feeding into "system" |
1042
|
|
|
|
|
|
|
or "exec", stepping around the shell). |
1043
|
|
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
Returns an aref of tokens (filenames, options, option-arguments). |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
Limitation: |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
The '--' option (which indicates that all following tokens are |
1049
|
|
|
|
|
|
|
file names, even if they begin with a hyphen) is not yet handled |
1050
|
|
|
|
|
|
|
correctly here. |
1051
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
=cut |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
# processing one char at a time |
1055
|
|
|
|
|
|
|
# different tokens have different syntax - when we know we're |
1056
|
|
|
|
|
|
|
# doing one type, we'll watch for it's ending |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
# quoted strings are treated as an additional token-type |
1059
|
|
|
|
|
|
|
# filenames are handled as option-arguments |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
# remember when you see quotes (toggle state) |
1062
|
|
|
|
|
|
|
# when you see an unquoted leading [-+], that begins an option |
1063
|
|
|
|
|
|
|
# [\s=] closes the option |
1064
|
|
|
|
|
|
|
# = means the following is an option-arg |
1065
|
|
|
|
|
|
|
# otherwise, it's an option-arg or a file if no leading [-+] |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
sub parse_ec_string { |
1068
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1069
|
|
|
|
|
|
|
|
1070
|
0
|
|
|
|
|
0
|
my $ec_string = shift; |
1071
|
0
|
|
|
|
|
0
|
my (@ec, $part); |
1072
|
|
|
|
|
|
|
|
1073
|
|
|
|
|
|
|
# drop leading and trailing whitespace |
1074
|
0
|
|
|
|
|
0
|
chomp($ec_string); |
1075
|
0
|
|
|
|
|
0
|
$ec_string =~ s/^\s//; |
1076
|
0
|
|
|
|
|
0
|
$ec_string =~ s/\s$//; |
1077
|
|
|
|
|
|
|
|
1078
|
|
|
|
|
|
|
# state flags |
1079
|
0
|
|
|
|
|
0
|
my $quoted = 0; |
1080
|
0
|
|
|
|
|
0
|
my $opted = 1; # begin saving whatever is there at the outset |
1081
|
0
|
|
|
|
|
0
|
my $arged = 0; |
1082
|
|
|
|
|
|
|
# 1-char of memory |
1083
|
0
|
|
|
|
|
0
|
my $prev = ''; |
1084
|
|
|
|
|
|
|
|
1085
|
0
|
|
|
|
|
0
|
my @chars = split '', $ec_string; |
1086
|
0
|
|
|
|
|
0
|
foreach (@chars) { |
1087
|
0
|
0
|
0
|
|
|
0
|
if ( /\s/ and $prev =~ /\s/ ) { # turn multiple spaces into one |
1088
|
0
|
|
|
|
|
0
|
next; |
1089
|
|
|
|
|
|
|
} |
1090
|
0
|
0
|
0
|
|
|
0
|
if ( not( $quoted) and /"/ ) { |
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
1091
|
0
|
|
|
|
|
0
|
$quoted = 1; |
1092
|
|
|
|
|
|
|
} elsif( ($quoted) and /"/ and $prev ne '\\') { # matches: " but not \" |
1093
|
0
|
|
|
|
|
0
|
$quoted = 0; |
1094
|
0
|
|
|
|
|
0
|
push @ec, $part; $part = ''; |
|
0
|
|
|
|
|
0
|
|
1095
|
|
|
|
|
|
|
} elsif ($quoted) { |
1096
|
|
|
|
|
|
|
# fold double backwhacks into one |
1097
|
0
|
0
|
0
|
|
|
0
|
if( $_ eq '\\' and $prev eq '\\' ){ |
1098
|
0
|
|
|
|
|
0
|
chop( $part ); |
1099
|
|
|
|
|
|
|
} |
1100
|
|
|
|
|
|
|
# drop escapes from escaped quotes |
1101
|
0
|
0
|
0
|
|
|
0
|
if( $_ eq '"' and $prev eq '\\' ) { |
1102
|
0
|
|
|
|
|
0
|
chop( $part ); |
1103
|
|
|
|
|
|
|
} |
1104
|
0
|
|
|
|
|
0
|
$part .= $_; |
1105
|
|
|
|
|
|
|
} elsif( not( $opted ) and /[-+]/ and $prev ne '\\' ) { |
1106
|
0
|
|
|
|
|
0
|
$arged = 1; |
1107
|
0
|
|
|
|
|
0
|
$part .= $_; |
1108
|
|
|
|
|
|
|
} elsif ( $opted and /[\s=]/ ) { |
1109
|
0
|
|
|
|
|
0
|
$opted = 0; |
1110
|
0
|
|
|
|
|
0
|
push @ec, $part; $part = ''; |
|
0
|
|
|
|
|
0
|
|
1111
|
|
|
|
|
|
|
} elsif ($opted) { |
1112
|
0
|
|
|
|
|
0
|
$part .= $_; |
1113
|
|
|
|
|
|
|
} elsif( not( $arged ) and ( $prev =~ /\s/ or ($prev eq '=') )) { # looks back ar prev char |
1114
|
0
|
|
|
|
|
0
|
$arged = 1; |
1115
|
0
|
|
|
|
|
0
|
$part .= $_; # must save-up this char (transition char was the previous one) |
1116
|
|
|
|
|
|
|
} elsif ($arged and /\s/ ) { |
1117
|
0
|
|
|
|
|
0
|
$arged = 0; |
1118
|
0
|
|
|
|
|
0
|
push @ec, $part; $part = ''; |
|
0
|
|
|
|
|
0
|
|
1119
|
|
|
|
|
|
|
} elsif ($arged) { |
1120
|
0
|
|
|
|
|
0
|
$part .= $_; |
1121
|
|
|
|
|
|
|
} |
1122
|
0
|
|
|
|
|
0
|
$prev = $_; |
1123
|
|
|
|
|
|
|
} |
1124
|
0
|
0
|
|
|
|
0
|
push @ec, $part unless( $part =~ /^\s*$/ ); # skipping blank lines (hack hack) |
1125
|
0
|
|
|
|
|
0
|
return \@ec; |
1126
|
|
|
|
|
|
|
} |
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
|
1129
|
|
|
|
|
|
|
=item clean_return_value |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
Cleans up a given string, trimming unwanted leading and trailing |
1132
|
|
|
|
|
|
|
blanks and double quotes. |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
This is intended to be used with elisp that uses the 'print' |
1135
|
|
|
|
|
|
|
function. Note that it is limited to elisp with a single print |
1136
|
|
|
|
|
|
|
of a result: multiple prints will leave embedded quote-newline |
1137
|
|
|
|
|
|
|
pairs in the output. |
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
=cut |
1140
|
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
sub clean_return_value { |
1142
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1143
|
0
|
|
|
|
|
0
|
my $string = shift; |
1144
|
0
|
|
|
|
|
0
|
$string =~ s{^[\s"]+}{}xms; |
1145
|
0
|
|
|
|
|
0
|
$string =~ s{[\s"]+$}{}xms; |
1146
|
0
|
|
|
|
|
0
|
return $string; |
1147
|
|
|
|
|
|
|
} |
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
|
1151
|
|
|
|
|
|
|
=item redirector_to_sod |
1152
|
|
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
Convert a redirector code into the equivalent shell_output_director |
1154
|
|
|
|
|
|
|
(Bourne shell). |
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
=cut |
1157
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
sub redirector_to_sod { |
1159
|
2
|
|
|
2
|
1
|
4
|
my $self = shift; |
1160
|
2
|
|
|
|
|
4
|
my $redirector = shift; |
1161
|
2
|
|
|
|
|
12
|
my $devnull = File::Spec->devnull; |
1162
|
|
|
|
|
|
|
|
1163
|
2
|
50
|
|
|
|
25
|
unless ( $redirector ) { |
1164
|
0
|
|
|
|
|
0
|
return; |
1165
|
|
|
|
|
|
|
} |
1166
|
|
|
|
|
|
|
|
1167
|
2
|
|
|
|
|
5
|
my $sod; |
1168
|
2
|
50
|
|
|
|
7
|
if( $redirector eq 'stdout_only' ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
1169
|
2
|
|
|
|
|
4
|
$sod = "2>$devnull"; |
1170
|
|
|
|
|
|
|
} elsif ( $redirector eq 'stderr_only' ) { |
1171
|
0
|
|
|
|
|
0
|
$sod = "2>&1 1>$devnull"; |
1172
|
|
|
|
|
|
|
} elsif ( $redirector eq 'all_output' ) { |
1173
|
0
|
|
|
|
|
0
|
$sod = '2>&1'; |
1174
|
|
|
|
|
|
|
} |
1175
|
2
|
|
|
|
|
14
|
return $sod; |
1176
|
|
|
|
|
|
|
} |
1177
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
=back |
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
=head2 Initialization Phase Methods |
1181
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
The following routines are largely used internally in the |
1183
|
|
|
|
|
|
|
object initialization phase. |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
=over |
1186
|
|
|
|
|
|
|
|
1187
|
|
|
|
|
|
|
=item process_emacs_libs_addition |
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
Goes through the given list of emacs_libs, and converts the names into |
1190
|
|
|
|
|
|
|
the lib_data style of data structure, appending it to lib_data. |
1191
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
Note that this method works on the given argument, without |
1193
|
|
|
|
|
|
|
reference to the object's "emacs_libs" field. |
1194
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
Returns a reference to a structure containing the new additions to lib_data. |
1196
|
|
|
|
|
|
|
|
1197
|
|
|
|
|
|
|
=cut |
1198
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
# Note: since set_up_ec_lib_loader qualifies the data and fills in |
1200
|
|
|
|
|
|
|
# likely values for type and priority, it need not be done here. |
1201
|
|
|
|
|
|
|
sub process_emacs_libs_addition { |
1202
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1203
|
0
|
|
|
|
|
0
|
my $libs = shift; |
1204
|
|
|
|
|
|
|
|
1205
|
0
|
|
|
|
|
0
|
my @new_lib_data; |
1206
|
0
|
|
|
|
|
0
|
foreach my $name ( @{ $libs } ) { |
|
0
|
|
|
|
|
0
|
|
1207
|
0
|
|
|
|
|
0
|
my $rec = [ $name, { type=>undef, priority=>undef } ]; |
1208
|
0
|
|
|
|
|
0
|
push @new_lib_data, $rec; |
1209
|
|
|
|
|
|
|
} |
1210
|
|
|
|
|
|
|
|
1211
|
0
|
|
|
|
|
0
|
my $lib_data = $self->lib_data; |
1212
|
0
|
|
|
|
|
0
|
push @{ $lib_data }, @new_lib_data; |
|
0
|
|
|
|
|
0
|
|
1213
|
0
|
|
|
|
|
0
|
$self->set_lib_data( $lib_data ); # called for side-effects: |
1214
|
|
|
|
|
|
|
# set_up_ec_lib_loader |
1215
|
0
|
|
|
|
|
0
|
return \@new_lib_data; |
1216
|
|
|
|
|
|
|
} |
1217
|
|
|
|
|
|
|
|
1218
|
|
|
|
|
|
|
=item process_emacs_libs_reset |
1219
|
|
|
|
|
|
|
|
1220
|
|
|
|
|
|
|
This converts the list of emacs_libs into the lib_data style of |
1221
|
|
|
|
|
|
|
structure much like L, but this |
1222
|
|
|
|
|
|
|
method resets the lib_data field to the given value at |
1223
|
|
|
|
|
|
|
init time (if any) before appending the new data. |
1224
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
Defaults to using the object's "emacs_libs" setting. |
1226
|
|
|
|
|
|
|
|
1227
|
|
|
|
|
|
|
Returns a reference to a structure containing the additions to lib_data |
1228
|
|
|
|
|
|
|
from emacs_libs. |
1229
|
|
|
|
|
|
|
|
1230
|
|
|
|
|
|
|
=cut |
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
sub process_emacs_libs_reset { |
1233
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1234
|
0
|
|
0
|
|
|
0
|
my $libs = shift || $self->emacs_libs; |
1235
|
|
|
|
|
|
|
|
1236
|
0
|
|
|
|
|
0
|
$self->reset_lib_data; |
1237
|
|
|
|
|
|
|
|
1238
|
0
|
|
|
|
|
0
|
my @new_lib_data; |
1239
|
0
|
|
|
|
|
0
|
foreach my $name ( @{ $libs } ) { |
|
0
|
|
|
|
|
0
|
|
1240
|
0
|
|
|
|
|
0
|
my $rec = [ $name, { type=>undef, priority=>undef } ]; |
1241
|
0
|
|
|
|
|
0
|
push @new_lib_data, $rec; |
1242
|
|
|
|
|
|
|
} |
1243
|
|
|
|
|
|
|
|
1244
|
0
|
|
|
|
|
0
|
my $lib_data = $self->lib_data; |
1245
|
0
|
|
|
|
|
0
|
push @{ $lib_data }, @new_lib_data; |
|
0
|
|
|
|
|
0
|
|
1246
|
0
|
|
|
|
|
0
|
$self->set_lib_data( $lib_data ); # called for side-effects: |
1247
|
|
|
|
|
|
|
# set_up_ec_lib_loader |
1248
|
0
|
|
|
|
|
0
|
return \@new_lib_data; |
1249
|
|
|
|
|
|
|
} |
1250
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
=item set_up_ec_lib_loader |
1252
|
|
|
|
|
|
|
|
1253
|
|
|
|
|
|
|
Initializes the ec_lib_loader attribute by scanning for the |
1254
|
|
|
|
|
|
|
appropriate emacs init file(s) and processing the list(s) of emacs |
1255
|
|
|
|
|
|
|
libraries specified in the object data. |
1256
|
|
|
|
|
|
|
|
1257
|
|
|
|
|
|
|
Returns the newly defined $ec_lib_loader string. |
1258
|
|
|
|
|
|
|
|
1259
|
|
|
|
|
|
|
This routine is called (indirectly) by L during object |
1260
|
|
|
|
|
|
|
initialization. |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
=cut |
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
sub set_up_ec_lib_loader { |
1265
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1266
|
|
|
|
|
|
|
|
1267
|
0
|
|
|
|
|
0
|
$self->genec_load_emacs_init; # zeroes out the ec_lib_loader string first |
1268
|
|
|
|
|
|
|
|
1269
|
0
|
|
|
|
|
0
|
my $lib_data = $self->lib_data; |
1270
|
|
|
|
|
|
|
|
1271
|
0
|
|
|
|
|
0
|
foreach my $rec (@{ $lib_data }) { |
|
0
|
|
|
|
|
0
|
|
1272
|
|
|
|
|
|
|
|
1273
|
0
|
|
|
|
|
0
|
my $name = $rec->[0]; |
1274
|
0
|
|
|
|
|
0
|
my $type = $rec->[1]->{type}; # file/lib |
1275
|
0
|
|
|
|
|
0
|
my $priority = $rec->[1]->{priority}; # needed/requested |
1276
|
|
|
|
|
|
|
|
1277
|
|
|
|
|
|
|
# qualify the lib_data |
1278
|
0
|
0
|
|
|
|
0
|
unless ( $type ) { |
1279
|
0
|
|
|
|
|
0
|
$type = $self->lib_or_file( $name ); |
1280
|
0
|
|
|
|
|
0
|
$rec->[1]->{type} = $type; |
1281
|
|
|
|
|
|
|
} |
1282
|
0
|
0
|
|
|
|
0
|
unless ( $priority ) { |
1283
|
0
|
|
|
|
|
0
|
$priority = $self->default_priority; |
1284
|
0
|
|
|
|
|
0
|
$rec->[1]->{priority} = $priority; |
1285
|
|
|
|
|
|
|
} |
1286
|
|
|
|
|
|
|
|
1287
|
0
|
|
|
|
|
0
|
my $method = sprintf "genec_loader_%s_%s", $type, $priority; |
1288
|
0
|
|
|
|
|
0
|
$self->$method( $name ); # appends to ec_lib_loader |
1289
|
|
|
|
|
|
|
} |
1290
|
|
|
|
|
|
|
|
1291
|
0
|
|
|
|
|
0
|
my $ec_lib_loader = $self->ec_lib_loader; |
1292
|
|
|
|
|
|
|
|
1293
|
0
|
|
|
|
|
0
|
return $ec_lib_loader; |
1294
|
|
|
|
|
|
|
} |
1295
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
=back |
1297
|
|
|
|
|
|
|
|
1298
|
|
|
|
|
|
|
=head2 Generation of Emacs Command Strings to Load Libraries |
1299
|
|
|
|
|
|
|
|
1300
|
|
|
|
|
|
|
These are routines run by L that generate a |
1301
|
|
|
|
|
|
|
string that can be included in an emacs command line invocation to |
1302
|
|
|
|
|
|
|
load certain libraries. Note the naming convention: "generate emacs |
1303
|
|
|
|
|
|
|
command-line" => "genec_". |
1304
|
|
|
|
|
|
|
|
1305
|
|
|
|
|
|
|
=over |
1306
|
|
|
|
|
|
|
|
1307
|
|
|
|
|
|
|
=item genec_load_emacs_init |
1308
|
|
|
|
|
|
|
|
1309
|
|
|
|
|
|
|
Generates an emacs command line fragment to load the |
1310
|
|
|
|
|
|
|
emacs_init file(s) as appropriate. |
1311
|
|
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
Side effect: zeroes out the ec_lib_loader before rebuilding with inits only. |
1313
|
|
|
|
|
|
|
|
1314
|
|
|
|
|
|
|
=cut |
1315
|
|
|
|
|
|
|
|
1316
|
|
|
|
|
|
|
sub genec_load_emacs_init { |
1317
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1318
|
|
|
|
|
|
|
|
1319
|
|
|
|
|
|
|
# start from clean slate |
1320
|
0
|
|
|
|
|
0
|
my $ec_lib_loader = $self->set_ec_lib_loader( '' ); |
1321
|
|
|
|
|
|
|
|
1322
|
0
|
|
|
|
|
0
|
my $load_no_inits = $self->load_no_inits; |
1323
|
0
|
0
|
|
|
|
0
|
if ( $load_no_inits ) { |
1324
|
0
|
|
|
|
|
0
|
return $ec_lib_loader; # empty string |
1325
|
|
|
|
|
|
|
} |
1326
|
|
|
|
|
|
|
|
1327
|
0
|
|
|
|
|
0
|
my $load_emacs_init = $self->load_emacs_init; |
1328
|
0
|
|
|
|
|
0
|
my $load_site_init = $self->load_site_init; |
1329
|
0
|
|
|
|
|
0
|
my $load_default_init = $self->load_default_init; |
1330
|
|
|
|
|
|
|
|
1331
|
0
|
0
|
0
|
|
|
0
|
if ( ( $load_site_init ) && ( $self->detect_site_init() ) ) { |
1332
|
0
|
|
|
|
|
0
|
my $ec = qq{ -l "site-start" }; |
1333
|
0
|
|
|
|
|
0
|
$self->append_to_ec_lib_loader( $ec ); |
1334
|
|
|
|
|
|
|
} |
1335
|
|
|
|
|
|
|
|
1336
|
0
|
0
|
|
|
|
0
|
if ($load_emacs_init) { |
1337
|
0
|
|
|
|
|
0
|
my $dot_emacs = $self->find_dot_emacs; |
1338
|
0
|
0
|
|
|
|
0
|
if ( $dot_emacs ) { |
1339
|
0
|
|
|
|
|
0
|
my $ec = qq{ -l "$dot_emacs" }; |
1340
|
0
|
|
|
|
|
0
|
$self->append_to_ec_lib_loader( $ec ); |
1341
|
|
|
|
|
|
|
} |
1342
|
|
|
|
|
|
|
} |
1343
|
|
|
|
|
|
|
|
1344
|
0
|
0
|
0
|
|
|
0
|
if ( ($load_default_init) && ($self->detect_lib( 'default' )) ) { |
1345
|
0
|
|
|
|
|
0
|
my $ec = qq{ -l "default" }; |
1346
|
0
|
|
|
|
|
0
|
$self->append_to_ec_lib_loader( $ec ); |
1347
|
|
|
|
|
|
|
} |
1348
|
|
|
|
|
|
|
|
1349
|
0
|
|
|
|
|
0
|
$ec_lib_loader = $self->ec_lib_loader; |
1350
|
0
|
|
|
|
|
0
|
return $ec_lib_loader; |
1351
|
|
|
|
|
|
|
} |
1352
|
|
|
|
|
|
|
|
1353
|
|
|
|
|
|
|
=item Genec Methods Called Dynamically |
1354
|
|
|
|
|
|
|
|
1355
|
|
|
|
|
|
|
The following is a set of four routines used by |
1356
|
|
|
|
|
|
|
"set_up_ec_lib_loader" to generate a string that can be included |
1357
|
|
|
|
|
|
|
in an emacs command line invocation to load the given library. |
1358
|
|
|
|
|
|
|
The methods here are named according to the pattern: |
1359
|
|
|
|
|
|
|
|
1360
|
|
|
|
|
|
|
"genec_loader_$type_$priority" |
1361
|
|
|
|
|
|
|
|
1362
|
|
|
|
|
|
|
where type is 'lib' or 'file' and priority is 'requested' or 'needed'. |
1363
|
|
|
|
|
|
|
|
1364
|
|
|
|
|
|
|
All of these methods return the generated string, but also append it |
1365
|
|
|
|
|
|
|
to the L attribute. |
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
=over |
1368
|
|
|
|
|
|
|
|
1369
|
|
|
|
|
|
|
=item genec_loader_lib_needed |
1370
|
|
|
|
|
|
|
|
1371
|
|
|
|
|
|
|
=cut |
1372
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
# used by set_up_ec_lib_loader |
1374
|
|
|
|
|
|
|
sub genec_loader_lib_needed { |
1375
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1376
|
0
|
|
|
|
|
0
|
my $name = shift; |
1377
|
|
|
|
|
|
|
|
1378
|
0
|
0
|
|
|
|
0
|
unless( defined( $name) ) { |
1379
|
0
|
|
|
|
|
0
|
return; |
1380
|
|
|
|
|
|
|
} |
1381
|
|
|
|
|
|
|
|
1382
|
0
|
|
|
|
|
0
|
my $ec = qq{ -l "$name" }; |
1383
|
|
|
|
|
|
|
# TODO what happens with names that contain double-quotes? |
1384
|
|
|
|
|
|
|
|
1385
|
0
|
|
|
|
|
0
|
$self->append_to_ec_lib_loader( $ec ); |
1386
|
0
|
|
|
|
|
0
|
return $ec; |
1387
|
|
|
|
|
|
|
} |
1388
|
|
|
|
|
|
|
|
1389
|
|
|
|
|
|
|
=item genec_loader_file_needed |
1390
|
|
|
|
|
|
|
|
1391
|
|
|
|
|
|
|
=cut |
1392
|
|
|
|
|
|
|
|
1393
|
|
|
|
|
|
|
# used by set_up_ec_lib_loader |
1394
|
|
|
|
|
|
|
sub genec_loader_file_needed { |
1395
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1396
|
0
|
|
|
|
|
0
|
my $name = shift; |
1397
|
|
|
|
|
|
|
|
1398
|
0
|
0
|
|
|
|
0
|
unless ( -e $name ) { |
1399
|
0
|
|
|
|
|
0
|
croak "Could not find required elisp library file: $name."; |
1400
|
|
|
|
|
|
|
} |
1401
|
0
|
|
|
|
|
0
|
my $elisp = |
1402
|
|
|
|
|
|
|
$self->quote_elisp( |
1403
|
|
|
|
|
|
|
$self->elisp_to_load_file( $name ) |
1404
|
|
|
|
|
|
|
); |
1405
|
0
|
|
|
|
|
0
|
my $ec = qq{ --eval "$elisp" }; |
1406
|
0
|
|
|
|
|
0
|
$self->append_to_ec_lib_loader( $ec ); |
1407
|
0
|
|
|
|
|
0
|
return $ec; |
1408
|
|
|
|
|
|
|
} |
1409
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
=item genec_loader_lib_requested |
1411
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
=cut |
1413
|
|
|
|
|
|
|
|
1414
|
|
|
|
|
|
|
# used by set_up_ec_lib_loader |
1415
|
|
|
|
|
|
|
sub genec_loader_lib_requested { |
1416
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1417
|
0
|
|
|
|
|
0
|
my $name = shift; |
1418
|
|
|
|
|
|
|
|
1419
|
0
|
0
|
|
|
|
0
|
unless ( $self->detect_lib( $name ) ) { |
1420
|
0
|
|
|
|
|
0
|
return; |
1421
|
|
|
|
|
|
|
} |
1422
|
|
|
|
|
|
|
|
1423
|
0
|
|
|
|
|
0
|
my $ec = qq{ -l "$name" }; |
1424
|
0
|
|
|
|
|
0
|
$self->append_to_ec_lib_loader( $ec ); |
1425
|
0
|
|
|
|
|
0
|
return $ec; |
1426
|
|
|
|
|
|
|
} |
1427
|
|
|
|
|
|
|
|
1428
|
|
|
|
|
|
|
=item genec_loader_file_requested |
1429
|
|
|
|
|
|
|
|
1430
|
|
|
|
|
|
|
=cut |
1431
|
|
|
|
|
|
|
|
1432
|
|
|
|
|
|
|
# used by set_up_ec_lib_loader |
1433
|
|
|
|
|
|
|
sub genec_loader_file_requested { |
1434
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1435
|
0
|
|
|
|
|
0
|
my $name = shift; |
1436
|
|
|
|
|
|
|
|
1437
|
0
|
0
|
|
|
|
0
|
unless( -e $name ) { |
1438
|
0
|
|
|
|
|
0
|
return; |
1439
|
|
|
|
|
|
|
} |
1440
|
|
|
|
|
|
|
|
1441
|
0
|
|
|
|
|
0
|
my $elisp = |
1442
|
|
|
|
|
|
|
$self->quote_elisp( |
1443
|
|
|
|
|
|
|
$self->elisp_to_load_file( $name ) |
1444
|
|
|
|
|
|
|
); |
1445
|
|
|
|
|
|
|
|
1446
|
0
|
|
|
|
|
0
|
my $ec = qq{ --eval "$elisp" }; |
1447
|
0
|
|
|
|
|
0
|
$self->append_to_ec_lib_loader( $ec ); |
1448
|
0
|
|
|
|
|
0
|
return $ec; |
1449
|
|
|
|
|
|
|
} |
1450
|
|
|
|
|
|
|
|
1451
|
|
|
|
|
|
|
=back |
1452
|
|
|
|
|
|
|
|
1453
|
|
|
|
|
|
|
=back |
1454
|
|
|
|
|
|
|
|
1455
|
|
|
|
|
|
|
=head2 Emacs probes |
1456
|
|
|
|
|
|
|
|
1457
|
|
|
|
|
|
|
Methods that return information about the emacs installation. |
1458
|
|
|
|
|
|
|
|
1459
|
|
|
|
|
|
|
=over |
1460
|
|
|
|
|
|
|
|
1461
|
|
|
|
|
|
|
=item probe_emacs_version |
1462
|
|
|
|
|
|
|
|
1463
|
|
|
|
|
|
|
Returns the version of the emacs program stored on your system. |
1464
|
|
|
|
|
|
|
This is called during the object initialization phase. |
1465
|
|
|
|
|
|
|
|
1466
|
|
|
|
|
|
|
It checks the emacs specified in the object's emacs_path |
1467
|
|
|
|
|
|
|
(which defaults to the simple command "emacs", sans any path), |
1468
|
|
|
|
|
|
|
and returns the version. |
1469
|
|
|
|
|
|
|
|
1470
|
|
|
|
|
|
|
As a side-effect, it sets a number of object attributes with |
1471
|
|
|
|
|
|
|
details about the emacs version: |
1472
|
|
|
|
|
|
|
|
1473
|
|
|
|
|
|
|
emacs_version |
1474
|
|
|
|
|
|
|
emacs_major_version |
1475
|
|
|
|
|
|
|
emacs_type |
1476
|
|
|
|
|
|
|
|
1477
|
|
|
|
|
|
|
Ignores redirector/shell_output_director. |
1478
|
|
|
|
|
|
|
|
1479
|
|
|
|
|
|
|
=cut |
1480
|
|
|
|
|
|
|
|
1481
|
|
|
|
|
|
|
sub probe_emacs_version { |
1482
|
2
|
|
|
2
|
1
|
3
|
my $self = shift; |
1483
|
2
|
|
|
|
|
3
|
my $opts = shift; |
1484
|
2
|
|
|
|
|
17
|
my $subname = ( caller(0) )[3]; |
1485
|
2
|
|
|
|
|
30
|
my $devnull = File::Spec->devnull(); |
1486
|
|
|
|
|
|
|
|
1487
|
2
|
|
|
|
|
4
|
my $redirector = 'stdout_only'; |
1488
|
2
|
|
|
|
|
9
|
my $sod = $self->redirector_to_sod( $redirector ); |
1489
|
|
|
|
|
|
|
|
1490
|
2
|
|
|
|
|
26
|
my $emacs = $self->emacs_path; |
1491
|
2
|
|
|
|
|
7
|
my $cmd = "$emacs --version $sod"; |
1492
|
2
|
|
|
|
|
29807
|
my $retval = qx{ $cmd }; |
1493
|
|
|
|
|
|
|
# $self->debug( "$subname:\n $retval\n" ); |
1494
|
|
|
|
|
|
|
|
1495
|
2
|
|
|
|
|
102
|
my $version = $self->parse_emacs_version_string( $retval ); |
1496
|
2
|
|
|
|
|
78
|
return $version; |
1497
|
|
|
|
|
|
|
} |
1498
|
|
|
|
|
|
|
|
1499
|
|
|
|
|
|
|
|
1500
|
|
|
|
|
|
|
=item parse_emacs_version_string |
1501
|
|
|
|
|
|
|
|
1502
|
|
|
|
|
|
|
The emacs version string returned from running "emacs --version" |
1503
|
|
|
|
|
|
|
is parsed by this routine, which picks out the version |
1504
|
|
|
|
|
|
|
numbers and so on and saves them as object data. |
1505
|
|
|
|
|
|
|
|
1506
|
|
|
|
|
|
|
See probe_emacs_version (which uses this internally). |
1507
|
|
|
|
|
|
|
|
1508
|
|
|
|
|
|
|
=cut |
1509
|
|
|
|
|
|
|
|
1510
|
|
|
|
|
|
|
# Note, a Gnu emacs version string has a first line like so: |
1511
|
|
|
|
|
|
|
# "GNU Emacs 22.1.1", |
1512
|
|
|
|
|
|
|
# followed by several other lines. |
1513
|
|
|
|
|
|
|
# |
1514
|
|
|
|
|
|
|
# For xemacs, the last line is important, though it's preceeded by |
1515
|
|
|
|
|
|
|
# various messages about for libraries loaded. |
1516
|
|
|
|
|
|
|
|
1517
|
|
|
|
|
|
|
# Typical version lines. |
1518
|
|
|
|
|
|
|
# GNU Emacs 22.1.1 |
1519
|
|
|
|
|
|
|
# GNU Emacs 22.1.92.1 |
1520
|
|
|
|
|
|
|
# GNU Emacs 23.0.0.1 |
1521
|
|
|
|
|
|
|
# GNU Emacs 21.4.1 |
1522
|
|
|
|
|
|
|
# XEmacs 21.4 (patch 18) "Social Property" [Lucid] (amd64-debian-linux, Mule) of Wed Dec 21 2005 on yellow |
1523
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
sub parse_emacs_version_string { |
1525
|
2
|
|
|
2
|
1
|
17
|
my $self = shift; |
1526
|
2
|
|
|
|
|
11
|
my $version_mess = shift; |
1527
|
2
|
50
|
|
|
|
38
|
unless( $version_mess ) { |
1528
|
2
|
|
|
|
|
16
|
return; |
1529
|
|
|
|
|
|
|
} |
1530
|
|
|
|
|
|
|
|
1531
|
0
|
|
|
|
|
0
|
my ($emacs_type, $version); |
1532
|
|
|
|
|
|
|
# TODO assuming versions are digits only (\d). Ever have letters, e.g. 'b'? |
1533
|
0
|
0
|
|
|
|
0
|
if ( $version_mess =~ m{^ ( GNU \s+ Emacs ) \s+ ( [\d.]* ) }xms ) { |
|
|
0
|
|
|
|
|
|
1534
|
0
|
|
|
|
|
0
|
$emacs_type = $1; |
1535
|
0
|
|
|
|
|
0
|
$version = $2; |
1536
|
|
|
|
|
|
|
} elsif ( $version_mess =~ m{ ^( XEmacs ) \s+ ( [\d.]* ) }xms ) { |
1537
|
0
|
|
|
|
|
0
|
$emacs_type = $1; |
1538
|
0
|
|
|
|
|
0
|
$version = $2; |
1539
|
|
|
|
|
|
|
} else { |
1540
|
0
|
|
|
|
|
0
|
$emacs_type ="not so gnu, not xemacs either"; |
1541
|
0
|
|
|
|
|
0
|
$version = ''; # silence uninitialized value warnings |
1542
|
|
|
|
|
|
|
} |
1543
|
0
|
|
|
|
|
0
|
$self->debug( "version: $version\n" ); |
1544
|
|
|
|
|
|
|
|
1545
|
0
|
|
|
|
|
0
|
$self->set_emacs_type( $emacs_type ); |
1546
|
0
|
|
|
|
|
0
|
$self->set_emacs_version( $version ); |
1547
|
|
|
|
|
|
|
|
1548
|
0
|
|
|
|
|
0
|
my (@v) = split /\./, $version; |
1549
|
|
|
|
|
|
|
|
1550
|
0
|
|
|
|
|
0
|
my $major_version; |
1551
|
0
|
0
|
|
|
|
0
|
if( defined( $v[0] ) ) { |
1552
|
0
|
|
|
|
|
0
|
$major_version = $v[0]; |
1553
|
|
|
|
|
|
|
} else { |
1554
|
0
|
|
|
|
|
0
|
$major_version = ''; # silence unitialized value warnings |
1555
|
|
|
|
|
|
|
} |
1556
|
0
|
|
|
|
|
0
|
$self->set_emacs_major_version( $major_version ); |
1557
|
0
|
|
|
|
|
0
|
$self->debug( "major_version: $major_version\n" ); |
1558
|
|
|
|
|
|
|
|
1559
|
0
|
|
|
|
|
0
|
return $version; |
1560
|
|
|
|
|
|
|
} |
1561
|
|
|
|
|
|
|
|
1562
|
|
|
|
|
|
|
=back |
1563
|
|
|
|
|
|
|
|
1564
|
|
|
|
|
|
|
=head2 Utilities Used by Initialization |
1565
|
|
|
|
|
|
|
|
1566
|
|
|
|
|
|
|
=over |
1567
|
|
|
|
|
|
|
|
1568
|
|
|
|
|
|
|
=item elisp_to_load_file |
1569
|
|
|
|
|
|
|
|
1570
|
|
|
|
|
|
|
Given the location of an emacs lisp file, generate the elisp |
1571
|
|
|
|
|
|
|
that ensures the library will be available and loaded. |
1572
|
|
|
|
|
|
|
|
1573
|
|
|
|
|
|
|
=cut |
1574
|
|
|
|
|
|
|
|
1575
|
|
|
|
|
|
|
sub elisp_to_load_file { |
1576
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1577
|
0
|
|
|
|
|
0
|
my $elisp_file = shift; |
1578
|
|
|
|
|
|
|
|
1579
|
0
|
|
|
|
|
0
|
my $path = dirname( $elisp_file ); |
1580
|
|
|
|
|
|
|
|
1581
|
0
|
|
|
|
|
0
|
my $elisp = qq{ |
1582
|
|
|
|
|
|
|
(progn |
1583
|
|
|
|
|
|
|
(add-to-list 'load-path |
1584
|
|
|
|
|
|
|
(expand-file-name "$path/")) |
1585
|
|
|
|
|
|
|
(load-file "$elisp_file")) |
1586
|
|
|
|
|
|
|
}; |
1587
|
|
|
|
|
|
|
} |
1588
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
=item find_dot_emacs |
1590
|
|
|
|
|
|
|
|
1591
|
|
|
|
|
|
|
Looks for one of the variants of the user's emacs init file |
1592
|
|
|
|
|
|
|
(e.g. "~/.emacs") in the same order that emacs would, and |
1593
|
|
|
|
|
|
|
returns the first one found. |
1594
|
|
|
|
|
|
|
|
1595
|
|
|
|
|
|
|
Note: this relies on the environment variable $HOME. (This |
1596
|
|
|
|
|
|
|
can be changed first to cause this to look for an emacs init |
1597
|
|
|
|
|
|
|
in some arbitrary location, e.g. for testing purposes.) |
1598
|
|
|
|
|
|
|
|
1599
|
|
|
|
|
|
|
This code does not issue a warning if the elc is stale compared to |
1600
|
|
|
|
|
|
|
the el, that's left up to emacs. |
1601
|
|
|
|
|
|
|
|
1602
|
|
|
|
|
|
|
=cut |
1603
|
|
|
|
|
|
|
|
1604
|
|
|
|
|
|
|
sub find_dot_emacs { |
1605
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1606
|
0
|
|
|
|
|
0
|
my @dot_emacs_candidates = ( |
1607
|
|
|
|
|
|
|
"$HOME/.emacs", |
1608
|
|
|
|
|
|
|
"$HOME/.emacs.elc", |
1609
|
|
|
|
|
|
|
"$HOME/.emacs.el", |
1610
|
|
|
|
|
|
|
"$HOME/.emacs.d/init.elc", |
1611
|
|
|
|
|
|
|
"$HOME/.emacs.d/init.el", |
1612
|
|
|
|
|
|
|
); |
1613
|
|
|
|
|
|
|
|
1614
|
0
|
|
|
0
|
|
0
|
my $dot_emacs = first { -e $_ } @dot_emacs_candidates; |
|
0
|
|
|
|
|
0
|
|
1615
|
0
|
|
|
|
|
0
|
return $dot_emacs; |
1616
|
|
|
|
|
|
|
} |
1617
|
|
|
|
|
|
|
|
1618
|
|
|
|
|
|
|
=item detect_site_init |
1619
|
|
|
|
|
|
|
|
1620
|
|
|
|
|
|
|
Looks for the "site-start.el" file in the raw load-path |
1621
|
|
|
|
|
|
|
without loading the regular emacs init file (e.g. ~/.emacs). |
1622
|
|
|
|
|
|
|
|
1623
|
|
|
|
|
|
|
Emacs itself normally loads this file before it loads |
1624
|
|
|
|
|
|
|
anything else, so this method replicates that behavior. |
1625
|
|
|
|
|
|
|
|
1626
|
|
|
|
|
|
|
Returns the library name ('site-start') if found, undef if not. |
1627
|
|
|
|
|
|
|
|
1628
|
|
|
|
|
|
|
Ignores redirector/shell_output_director. |
1629
|
|
|
|
|
|
|
|
1630
|
|
|
|
|
|
|
=cut |
1631
|
|
|
|
|
|
|
|
1632
|
|
|
|
|
|
|
# runs an emacs batch process as a probe, and if the command |
1633
|
|
|
|
|
|
|
# runs "successfully", it checks the return value, and parses |
1634
|
|
|
|
|
|
|
# it to see if the library was in fact found. |
1635
|
|
|
|
|
|
|
|
1636
|
|
|
|
|
|
|
# Note that this routine can not easily be written to use |
1637
|
|
|
|
|
|
|
# detect_lib below, because of the different handling of .emacs |
1638
|
|
|
|
|
|
|
|
1639
|
|
|
|
|
|
|
sub detect_site_init { |
1640
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1641
|
0
|
|
|
|
|
0
|
my $opts = shift; |
1642
|
0
|
|
|
|
|
0
|
my $subname = ( caller(0) )[3]; |
1643
|
|
|
|
|
|
|
|
1644
|
0
|
|
|
|
|
0
|
my $redirector = 'all_output'; |
1645
|
0
|
|
|
|
|
0
|
my $sod = $self->redirector_to_sod( $redirector ); |
1646
|
|
|
|
|
|
|
|
1647
|
0
|
|
|
|
|
0
|
my $emacs = $self->emacs_path; |
1648
|
0
|
|
|
|
|
0
|
my $before_hook = $self->before_hook; |
1649
|
0
|
|
|
|
|
0
|
my $lib_name = 'site-start'; |
1650
|
|
|
|
|
|
|
|
1651
|
0
|
|
|
|
|
0
|
my $cmd = qq{ $emacs --batch $before_hook -l $lib_name $sod }; |
1652
|
0
|
|
|
|
|
0
|
$self->debug("$subname cmd:\n $cmd\n"); |
1653
|
|
|
|
|
|
|
|
1654
|
0
|
|
|
|
|
0
|
my $retval = qx{ $cmd }; |
1655
|
0
|
|
|
|
|
0
|
$self->debug("$subname retval:\n $retval\n"); |
1656
|
|
|
|
|
|
|
|
1657
|
0
|
0
|
0
|
|
|
0
|
if ( defined( $retval ) && |
1658
|
|
|
|
|
|
|
$retval =~ |
1659
|
|
|
|
|
|
|
m{\bCannot \s+ open \s+ load \s+ file: \s+ $lib_name \b}xms ) { |
1660
|
0
|
|
|
|
|
0
|
return; |
1661
|
|
|
|
|
|
|
} else { |
1662
|
0
|
|
|
|
|
0
|
return $lib_name; |
1663
|
|
|
|
|
|
|
} |
1664
|
|
|
|
|
|
|
} |
1665
|
|
|
|
|
|
|
|
1666
|
|
|
|
|
|
|
=item detect_lib |
1667
|
|
|
|
|
|
|
|
1668
|
|
|
|
|
|
|
Looks for the given elisp library in the load-path after |
1669
|
|
|
|
|
|
|
trying to load the given list of context_libs (that includes .emacs |
1670
|
|
|
|
|
|
|
as appropriate, and this method uses the requested_load_files as |
1671
|
|
|
|
|
|
|
context, as well). |
1672
|
|
|
|
|
|
|
|
1673
|
|
|
|
|
|
|
Returns $lib if found, undef if not. |
1674
|
|
|
|
|
|
|
|
1675
|
|
|
|
|
|
|
Example usage: |
1676
|
|
|
|
|
|
|
|
1677
|
|
|
|
|
|
|
if ( $self->detect_lib("dired") ) { |
1678
|
|
|
|
|
|
|
print "As expected, dired.el is installed."; |
1679
|
|
|
|
|
|
|
} |
1680
|
|
|
|
|
|
|
|
1681
|
|
|
|
|
|
|
my @good_libs = grep { defined($_) } map{ $self->detect_lib($_) } @candidate_libs; |
1682
|
|
|
|
|
|
|
|
1683
|
|
|
|
|
|
|
Ignores redirector/shell_output_director. |
1684
|
|
|
|
|
|
|
|
1685
|
|
|
|
|
|
|
=cut |
1686
|
|
|
|
|
|
|
|
1687
|
|
|
|
|
|
|
sub detect_lib { |
1688
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1689
|
0
|
|
|
|
|
0
|
my $lib = shift; |
1690
|
0
|
|
|
|
|
0
|
my $opts = shift; |
1691
|
0
|
|
|
|
|
0
|
my $subname = (caller(0))[3]; |
1692
|
|
|
|
|
|
|
|
1693
|
0
|
0
|
|
|
|
0
|
return unless $lib; |
1694
|
|
|
|
|
|
|
|
1695
|
0
|
|
|
|
|
0
|
my $redirector = 'all_output'; |
1696
|
0
|
|
|
|
|
0
|
my $sod = $self->redirector_to_sod( $redirector ); |
1697
|
|
|
|
|
|
|
|
1698
|
0
|
|
|
|
|
0
|
my $emacs = $self->emacs_path; |
1699
|
0
|
|
|
|
|
0
|
my $before_hook = $self->before_hook; |
1700
|
0
|
|
|
|
|
0
|
my $ec_head = qq{ $emacs --batch $before_hook }; |
1701
|
|
|
|
|
|
|
# cmd string to load existing, presumably vetted, libs |
1702
|
0
|
|
|
|
|
0
|
my $ec_lib_loader = $self->ec_lib_loader; |
1703
|
|
|
|
|
|
|
|
1704
|
0
|
|
|
|
|
0
|
my $cmd = qq{ $ec_head $ec_lib_loader -l $lib $sod}; |
1705
|
0
|
|
|
|
|
0
|
my $retval = qx{ $cmd }; |
1706
|
|
|
|
|
|
|
|
1707
|
0
|
0
|
0
|
|
|
0
|
if ( defined( $retval ) && |
1708
|
|
|
|
|
|
|
$retval =~ m{\bCannot \s+ open \s+ load \s+ file: \s+ $lib \b}xms ) { |
1709
|
0
|
|
|
|
|
0
|
return; |
1710
|
|
|
|
|
|
|
} else { |
1711
|
0
|
|
|
|
|
0
|
return $lib; |
1712
|
|
|
|
|
|
|
} |
1713
|
|
|
|
|
|
|
} |
1714
|
|
|
|
|
|
|
|
1715
|
|
|
|
|
|
|
|
1716
|
|
|
|
|
|
|
=item lib_or_file |
1717
|
|
|
|
|
|
|
|
1718
|
|
|
|
|
|
|
Given the name of an emacs library, examine it to see if it |
1719
|
|
|
|
|
|
|
looks like a file system path, or an emacs library (technically |
1720
|
|
|
|
|
|
|
a "feature name", i.e. sans path or extension). |
1721
|
|
|
|
|
|
|
|
1722
|
|
|
|
|
|
|
Returns a string, either "file" or "lib". |
1723
|
|
|
|
|
|
|
|
1724
|
|
|
|
|
|
|
=cut |
1725
|
|
|
|
|
|
|
|
1726
|
|
|
|
|
|
|
sub lib_or_file { |
1727
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1728
|
0
|
|
|
|
|
0
|
my $name = shift; |
1729
|
|
|
|
|
|
|
|
1730
|
0
|
|
|
|
|
0
|
my $path_found; |
1731
|
0
|
|
|
|
|
0
|
my ($volume,$directories,$file) = File::Spec->splitpath( $name ); |
1732
|
0
|
0
|
0
|
|
|
0
|
if( $directories || $volume ) { |
1733
|
0
|
|
|
|
|
0
|
$path_found = 1; |
1734
|
|
|
|
|
|
|
} |
1735
|
|
|
|
|
|
|
|
1736
|
0
|
|
|
|
|
0
|
my $ext_found = ( $name =~ m{\.el[c]?$}xms ); |
1737
|
|
|
|
|
|
|
|
1738
|
0
|
|
|
|
|
0
|
my $type; |
1739
|
0
|
0
|
|
|
|
0
|
if ($path_found) { |
|
|
0
|
|
|
|
|
|
1740
|
0
|
|
|
|
|
0
|
$type = 'file'; |
1741
|
|
|
|
|
|
|
} elsif ($ext_found) { |
1742
|
0
|
|
|
|
|
0
|
$type = 'file'; |
1743
|
|
|
|
|
|
|
} else { |
1744
|
0
|
|
|
|
|
0
|
$type = 'lib'; |
1745
|
|
|
|
|
|
|
} |
1746
|
0
|
|
|
|
|
0
|
return $type; |
1747
|
|
|
|
|
|
|
} |
1748
|
|
|
|
|
|
|
|
1749
|
|
|
|
|
|
|
|
1750
|
|
|
|
|
|
|
=back |
1751
|
|
|
|
|
|
|
|
1752
|
|
|
|
|
|
|
=head2 Routines in Use by Some External Libraries |
1753
|
|
|
|
|
|
|
|
1754
|
|
|
|
|
|
|
These aren't expected to be generally useful methods, but |
1755
|
|
|
|
|
|
|
they are in use by some code (notably L). |
1756
|
|
|
|
|
|
|
|
1757
|
|
|
|
|
|
|
=over |
1758
|
|
|
|
|
|
|
|
1759
|
|
|
|
|
|
|
=item elisp_file_from_library_name_if_in_loadpath |
1760
|
|
|
|
|
|
|
|
1761
|
|
|
|
|
|
|
Identifies the file associated with a given elisp library name by |
1762
|
|
|
|
|
|
|
shelling out to emacs in batch mode. |
1763
|
|
|
|
|
|
|
|
1764
|
|
|
|
|
|
|
=cut |
1765
|
|
|
|
|
|
|
|
1766
|
|
|
|
|
|
|
# used externally by Emacs::Run::ExtractDocs |
1767
|
|
|
|
|
|
|
sub elisp_file_from_library_name_if_in_loadpath { |
1768
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1769
|
0
|
|
|
|
|
0
|
my $library = shift; |
1770
|
0
|
|
|
|
|
0
|
my $subname = (caller(0))[3]; |
1771
|
|
|
|
|
|
|
|
1772
|
0
|
|
|
|
|
0
|
my $elisp = qq{ |
1773
|
|
|
|
|
|
|
(progn |
1774
|
|
|
|
|
|
|
(setq codefile (locate-library "$library")) |
1775
|
|
|
|
|
|
|
(message codefile)) |
1776
|
|
|
|
|
|
|
}; |
1777
|
|
|
|
|
|
|
|
1778
|
0
|
|
|
|
|
0
|
my $return = $self->eval_elisp( $elisp ); |
1779
|
|
|
|
|
|
|
|
1780
|
0
|
|
|
|
|
0
|
my $last_line = ( split /\n/, $return )[-1]; |
1781
|
|
|
|
|
|
|
|
1782
|
0
|
|
|
|
|
0
|
my $file; |
1783
|
0
|
0
|
0
|
|
|
0
|
if ( ($last_line) && (-e $last_line) ) { |
1784
|
0
|
|
|
|
|
0
|
$self->debug( "$subname: $last_line is associated with $library\n" ); |
1785
|
0
|
|
|
|
|
0
|
$file = $last_line; |
1786
|
|
|
|
|
|
|
} else { |
1787
|
0
|
|
|
|
|
0
|
$self->debug( "$subname: no file name found for lib: $library\n" ); |
1788
|
0
|
|
|
|
|
0
|
$file = undef; |
1789
|
|
|
|
|
|
|
} |
1790
|
|
|
|
|
|
|
|
1791
|
0
|
|
|
|
|
0
|
return $file; |
1792
|
|
|
|
|
|
|
} |
1793
|
|
|
|
|
|
|
|
1794
|
|
|
|
|
|
|
=item generate_elisp_to_load_library |
1795
|
|
|
|
|
|
|
|
1796
|
|
|
|
|
|
|
Generates elisp code that will instruct emacs to load the given |
1797
|
|
|
|
|
|
|
library. It also makes sure it's location is in the load-path, which |
1798
|
|
|
|
|
|
|
is not precisely the same thing: See "Loaded vs. in load-path". |
1799
|
|
|
|
|
|
|
|
1800
|
|
|
|
|
|
|
Takes one argument, which can either be the name of the library, or |
1801
|
|
|
|
|
|
|
the name of the file, as distinguished by the presence of a ".el" |
1802
|
|
|
|
|
|
|
extension on a file name. Also, the file name will usually have a |
1803
|
|
|
|
|
|
|
path included, but the library name can not. |
1804
|
|
|
|
|
|
|
|
1805
|
|
|
|
|
|
|
=cut |
1806
|
|
|
|
|
|
|
|
1807
|
|
|
|
|
|
|
# used externally by Emacs::Run::ExtractDocs |
1808
|
|
|
|
|
|
|
sub generate_elisp_to_load_library { |
1809
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1810
|
0
|
|
|
|
|
0
|
my $arg = shift; |
1811
|
|
|
|
|
|
|
|
1812
|
0
|
|
|
|
|
0
|
my ($elisp, $elisp_file); |
1813
|
0
|
0
|
|
|
|
0
|
if ($arg =~ m{\.el$}){ |
1814
|
0
|
|
|
|
|
0
|
$elisp_file = $arg; |
1815
|
0
|
|
|
|
|
0
|
$elisp = $self->elisp_to_load_file( $elisp_file ); |
1816
|
|
|
|
|
|
|
} else { |
1817
|
|
|
|
|
|
|
|
1818
|
0
|
|
|
|
|
0
|
$elisp_file = $self->elisp_file_from_library_name_if_in_loadpath( $arg ); |
1819
|
|
|
|
|
|
|
|
1820
|
0
|
0
|
|
|
|
0
|
unless( $elisp_file ) { |
1821
|
0
|
|
|
|
|
0
|
croak "Could not determine the file for the named library: $arg"; |
1822
|
|
|
|
|
|
|
} |
1823
|
|
|
|
|
|
|
|
1824
|
0
|
|
|
|
|
0
|
$elisp = $self->elisp_to_load_file( $elisp_file ); |
1825
|
|
|
|
|
|
|
} |
1826
|
0
|
|
|
|
|
0
|
return $elisp; |
1827
|
|
|
|
|
|
|
} |
1828
|
|
|
|
|
|
|
|
1829
|
|
|
|
|
|
|
|
1830
|
|
|
|
|
|
|
=back |
1831
|
|
|
|
|
|
|
|
1832
|
|
|
|
|
|
|
=head2 Basic Setters and Getters |
1833
|
|
|
|
|
|
|
|
1834
|
|
|
|
|
|
|
The naming convention in use here is that setters begin with |
1835
|
|
|
|
|
|
|
"set_", but getters have *no* prefix: the most commonly used case |
1836
|
|
|
|
|
|
|
deserves the simplest syntax (and mutators are deprecated). |
1837
|
|
|
|
|
|
|
|
1838
|
|
|
|
|
|
|
Setters and getters exist for all of the object attributes which are |
1839
|
|
|
|
|
|
|
documented with the L method (but note that these exist even for |
1840
|
|
|
|
|
|
|
"internal" attributes that are not expected to be useful to the client |
1841
|
|
|
|
|
|
|
coder). |
1842
|
|
|
|
|
|
|
|
1843
|
|
|
|
|
|
|
=head2 Special Accessors |
1844
|
|
|
|
|
|
|
|
1845
|
|
|
|
|
|
|
=over |
1846
|
|
|
|
|
|
|
|
1847
|
|
|
|
|
|
|
=item append_to_ec_lib_loader |
1848
|
|
|
|
|
|
|
|
1849
|
|
|
|
|
|
|
Non-standard setter that appends the given string to the |
1850
|
|
|
|
|
|
|
the L attribute. |
1851
|
|
|
|
|
|
|
|
1852
|
|
|
|
|
|
|
=cut |
1853
|
|
|
|
|
|
|
|
1854
|
|
|
|
|
|
|
sub append_to_ec_lib_loader { |
1855
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1856
|
0
|
|
|
|
|
0
|
my $append_string = shift; |
1857
|
|
|
|
|
|
|
|
1858
|
0
|
|
0
|
|
|
0
|
my $ec_lib_loader = $self->{ ec_lib_loader } || ''; |
1859
|
0
|
|
|
|
|
0
|
$ec_lib_loader .= $append_string; |
1860
|
|
|
|
|
|
|
|
1861
|
0
|
|
|
|
|
0
|
$self->{ ec_lib_loader } = $ec_lib_loader; |
1862
|
|
|
|
|
|
|
|
1863
|
0
|
|
|
|
|
0
|
return $ec_lib_loader; |
1864
|
|
|
|
|
|
|
} |
1865
|
|
|
|
|
|
|
|
1866
|
|
|
|
|
|
|
|
1867
|
|
|
|
|
|
|
=item append_to_before_hook |
1868
|
|
|
|
|
|
|
|
1869
|
|
|
|
|
|
|
Non-standard setter that appends the given string to the |
1870
|
|
|
|
|
|
|
the L attribute. |
1871
|
|
|
|
|
|
|
|
1872
|
|
|
|
|
|
|
Under some circumstances, this module uses the L for |
1873
|
|
|
|
|
|
|
internal purposes (for -Q and --no-splash), so using an ordinary |
1874
|
|
|
|
|
|
|
setter might erase something you didn't realize was there. |
1875
|
|
|
|
|
|
|
Typically it's safer to do an append to the L by |
1876
|
|
|
|
|
|
|
using this method. |
1877
|
|
|
|
|
|
|
|
1878
|
|
|
|
|
|
|
=cut |
1879
|
|
|
|
|
|
|
|
1880
|
|
|
|
|
|
|
sub append_to_before_hook { |
1881
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1882
|
0
|
|
|
|
|
0
|
my $append_string = shift; |
1883
|
|
|
|
|
|
|
|
1884
|
0
|
|
0
|
|
|
0
|
my $before_hook = $self->{ before_hook } || ''; |
1885
|
0
|
|
|
|
|
0
|
$before_hook .= $append_string; |
1886
|
|
|
|
|
|
|
|
1887
|
0
|
|
|
|
|
0
|
$self->{ before_hook } = $before_hook; |
1888
|
|
|
|
|
|
|
|
1889
|
0
|
|
|
|
|
0
|
return $before_hook; |
1890
|
|
|
|
|
|
|
} |
1891
|
|
|
|
|
|
|
|
1892
|
|
|
|
|
|
|
=back |
1893
|
|
|
|
|
|
|
|
1894
|
|
|
|
|
|
|
=head2 accessors that effect the L attribute |
1895
|
|
|
|
|
|
|
|
1896
|
|
|
|
|
|
|
If either lib_data or emacs_libs is modified, this must |
1897
|
|
|
|
|
|
|
trigger another run of L to keep |
1898
|
|
|
|
|
|
|
the L string up-to-date. |
1899
|
|
|
|
|
|
|
|
1900
|
|
|
|
|
|
|
=over |
1901
|
|
|
|
|
|
|
|
1902
|
|
|
|
|
|
|
=item set_lib_data |
1903
|
|
|
|
|
|
|
|
1904
|
|
|
|
|
|
|
Setter for lib_data. |
1905
|
|
|
|
|
|
|
|
1906
|
|
|
|
|
|
|
=cut |
1907
|
|
|
|
|
|
|
|
1908
|
|
|
|
|
|
|
sub set_lib_data { |
1909
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1910
|
0
|
|
|
|
|
0
|
my $lib_data = shift; |
1911
|
0
|
|
|
|
|
0
|
$self->{ lib_data } = $lib_data; |
1912
|
0
|
|
|
|
|
0
|
$self->set_up_ec_lib_loader; |
1913
|
0
|
|
|
|
|
0
|
return $lib_data; |
1914
|
|
|
|
|
|
|
} |
1915
|
|
|
|
|
|
|
|
1916
|
|
|
|
|
|
|
|
1917
|
|
|
|
|
|
|
=item reset_lib_data |
1918
|
|
|
|
|
|
|
|
1919
|
|
|
|
|
|
|
Reverts lib_data to the value supplied during |
1920
|
|
|
|
|
|
|
initization (it empties it entirely, if none was supplied). |
1921
|
|
|
|
|
|
|
|
1922
|
|
|
|
|
|
|
Note: this does not (at present) trigger a re-build of L, |
1923
|
|
|
|
|
|
|
because it's presumed that this will be triggered by some step |
1924
|
|
|
|
|
|
|
following this one. |
1925
|
|
|
|
|
|
|
|
1926
|
|
|
|
|
|
|
=cut |
1927
|
|
|
|
|
|
|
|
1928
|
|
|
|
|
|
|
sub reset_lib_data { |
1929
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1930
|
0
|
|
|
|
|
0
|
@{ $self->{ lib_data } } = @{ $self->{ lib_data_given } }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
1931
|
0
|
|
|
|
|
0
|
return $self->{ lib_data }; |
1932
|
|
|
|
|
|
|
} |
1933
|
|
|
|
|
|
|
|
1934
|
|
|
|
|
|
|
|
1935
|
|
|
|
|
|
|
|
1936
|
|
|
|
|
|
|
=item set_emacs_libs |
1937
|
|
|
|
|
|
|
|
1938
|
|
|
|
|
|
|
Setter for emacs_libs. |
1939
|
|
|
|
|
|
|
|
1940
|
|
|
|
|
|
|
Side effect: runs process_emacs_libs_rest on the given emacs_libs |
1941
|
|
|
|
|
|
|
list. |
1942
|
|
|
|
|
|
|
|
1943
|
|
|
|
|
|
|
process_emacs_libs_reset indirectly calls set_up_ec_lib_loader |
1944
|
|
|
|
|
|
|
so we don't need to do so explicitly here. |
1945
|
|
|
|
|
|
|
|
1946
|
|
|
|
|
|
|
=cut |
1947
|
|
|
|
|
|
|
|
1948
|
|
|
|
|
|
|
sub set_emacs_libs { |
1949
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1950
|
0
|
|
|
|
|
0
|
my $emacs_libs = shift; |
1951
|
0
|
|
|
|
|
0
|
$self->{ emacs_libs } = $emacs_libs; |
1952
|
0
|
|
|
|
|
0
|
$self->process_emacs_libs_reset( $emacs_libs ); |
1953
|
0
|
|
|
|
|
0
|
return $emacs_libs; |
1954
|
|
|
|
|
|
|
} |
1955
|
|
|
|
|
|
|
|
1956
|
|
|
|
|
|
|
=item push_emacs_libs |
1957
|
|
|
|
|
|
|
|
1958
|
|
|
|
|
|
|
Pushes a new lib to the emacs_libs array. |
1959
|
|
|
|
|
|
|
|
1960
|
|
|
|
|
|
|
Takes a string, returns aref of the full list of emacs_libs. |
1961
|
|
|
|
|
|
|
|
1962
|
|
|
|
|
|
|
Side-effect: runs process_emacs_libs_addition on the new lib, |
1963
|
|
|
|
|
|
|
(appending the new info to lib_data). |
1964
|
|
|
|
|
|
|
|
1965
|
|
|
|
|
|
|
process_emacs_libs_addition indirectly calls set_up_ec_lib_loader |
1966
|
|
|
|
|
|
|
so we don't need to do so explicitly here. |
1967
|
|
|
|
|
|
|
|
1968
|
|
|
|
|
|
|
=cut |
1969
|
|
|
|
|
|
|
|
1970
|
|
|
|
|
|
|
sub push_emacs_libs { |
1971
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1972
|
0
|
|
|
|
|
0
|
my $newlib = shift; |
1973
|
|
|
|
|
|
|
|
1974
|
0
|
|
|
|
|
0
|
my $emacs_libs = $self->emacs_libs; |
1975
|
0
|
|
|
|
|
0
|
push @{ $emacs_libs }, $newlib; |
|
0
|
|
|
|
|
0
|
|
1976
|
0
|
|
|
|
|
0
|
$self->process_emacs_libs_addition( [ $newlib ] ); |
1977
|
0
|
|
|
|
|
0
|
return $emacs_libs; |
1978
|
|
|
|
|
|
|
} |
1979
|
|
|
|
|
|
|
|
1980
|
|
|
|
|
|
|
=item set_redirector |
1981
|
|
|
|
|
|
|
|
1982
|
|
|
|
|
|
|
Setter for object attribute set_redirector. |
1983
|
|
|
|
|
|
|
Automatically sets the shell_output_director field. |
1984
|
|
|
|
|
|
|
|
1985
|
|
|
|
|
|
|
=cut |
1986
|
|
|
|
|
|
|
|
1987
|
|
|
|
|
|
|
sub set_redirector { |
1988
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
1989
|
0
|
|
|
|
|
0
|
my $redirector = shift; |
1990
|
0
|
|
|
|
|
0
|
$self->{ redirector } = $redirector; |
1991
|
|
|
|
|
|
|
|
1992
|
0
|
|
|
|
|
0
|
$self->{ shell_output_director } = $self->redirector_to_sod( $redirector ); |
1993
|
|
|
|
|
|
|
|
1994
|
0
|
|
|
|
|
0
|
return $redirector; |
1995
|
|
|
|
|
|
|
} |
1996
|
|
|
|
|
|
|
|
1997
|
|
|
|
|
|
|
|
1998
|
|
|
|
|
|
|
|
1999
|
|
|
|
|
|
|
|
2000
|
|
|
|
|
|
|
# automatic generation of the basic setters and getters |
2001
|
|
|
|
|
|
|
sub AUTOLOAD { |
2002
|
2
|
50
|
|
2
|
|
9
|
return if $AUTOLOAD =~ /DESTROY$/; # skip calls to DESTROY () |
2003
|
|
|
|
|
|
|
|
2004
|
2
|
|
|
|
|
14
|
my ($name) = $AUTOLOAD =~ /([^:]+)$/; # extract method name |
2005
|
2
|
|
|
|
|
5
|
(my $field = $name) =~ s/^set_//; |
2006
|
|
|
|
|
|
|
|
2007
|
|
|
|
|
|
|
# check that this is a valid accessor call |
2008
|
2
|
50
|
|
|
|
8
|
croak("Unknown method '$AUTOLOAD' called") |
2009
|
|
|
|
|
|
|
unless defined( $ATTRIBUTES{ $field } ); |
2010
|
|
|
|
|
|
|
|
2011
|
3
|
|
|
3
|
|
48
|
{ no strict 'refs'; |
|
3
|
|
|
|
|
63
|
|
|
3
|
|
|
|
|
962
|
|
|
2
|
|
|
|
|
3
|
|
2012
|
|
|
|
|
|
|
|
2013
|
|
|
|
|
|
|
# create the setter and getter and install them in the symbol table |
2014
|
|
|
|
|
|
|
|
2015
|
2
|
50
|
|
|
|
17
|
if ( $name =~ /^set_/ ) { |
|
|
50
|
|
|
|
|
|
2016
|
|
|
|
|
|
|
|
2017
|
|
|
|
|
|
|
*$name = sub { |
2018
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
2019
|
0
|
|
|
|
|
0
|
$self->{ $field } = shift; |
2020
|
0
|
|
|
|
|
0
|
return $self->{ $field }; |
2021
|
0
|
|
|
|
|
0
|
}; |
2022
|
|
|
|
|
|
|
|
2023
|
0
|
|
|
|
|
0
|
goto &$name; # jump to the new method. |
2024
|
|
|
|
|
|
|
} elsif ( $name =~ /^get_/ ) { |
2025
|
0
|
|
|
|
|
0
|
carp("Apparent attempt at using a getter with unneeded 'get_' prefix."); |
2026
|
|
|
|
|
|
|
} |
2027
|
|
|
|
|
|
|
|
2028
|
|
|
|
|
|
|
*$name = sub { |
2029
|
2
|
|
|
2
|
|
3
|
my $self = shift; |
2030
|
2
|
|
|
|
|
15
|
return $self->{ $field }; |
2031
|
2
|
|
|
|
|
12
|
}; |
2032
|
|
|
|
|
|
|
|
2033
|
2
|
|
|
|
|
66
|
goto &$name; # jump to the new method. |
2034
|
|
|
|
|
|
|
} |
2035
|
|
|
|
|
|
|
} |
2036
|
|
|
|
|
|
|
|
2037
|
|
|
|
|
|
|
|
2038
|
|
|
|
|
|
|
1; |
2039
|
|
|
|
|
|
|
|
2040
|
|
|
|
|
|
|
### end of code |
2041
|
|
|
|
|
|
|
|
2042
|
|
|
|
|
|
|
=back |
2043
|
|
|
|
|
|
|
|
2044
|
|
|
|
|
|
|
=head2 Controlling Output Redirection |
2045
|
|
|
|
|
|
|
|
2046
|
|
|
|
|
|
|
As described under L, the L is a code used to |
2047
|
|
|
|
|
|
|
control what happens to the output streams STDOUT and STDERR (or |
2048
|
|
|
|
|
|
|
in elisp terms, the output from "print" or "message"): |
2049
|
|
|
|
|
|
|
B, B or B. |
2050
|
|
|
|
|
|
|
|
2051
|
|
|
|
|
|
|
The client programmer may not need to worry about the L at |
2052
|
|
|
|
|
|
|
all, since some (hopefully) sensible defaults have been chosen for the |
2053
|
|
|
|
|
|
|
major methods here: |
2054
|
|
|
|
|
|
|
|
2055
|
|
|
|
|
|
|
all_output (using the object default) |
2056
|
|
|
|
|
|
|
|
2057
|
|
|
|
|
|
|
eval_elisp |
2058
|
|
|
|
|
|
|
run_elisp_on_file |
2059
|
|
|
|
|
|
|
|
2060
|
|
|
|
|
|
|
stdout_only (special method-level defaults) |
2061
|
|
|
|
|
|
|
|
2062
|
|
|
|
|
|
|
get_load_path |
2063
|
|
|
|
|
|
|
get_variable |
2064
|
|
|
|
|
|
|
eval_function |
2065
|
|
|
|
|
|
|
|
2066
|
|
|
|
|
|
|
In addition to being able to set L at instantiation |
2067
|
|
|
|
|
|
|
(as an option to L), L can also often be set |
2068
|
|
|
|
|
|
|
at the method level to temporarily override the object-level setting. |
2069
|
|
|
|
|
|
|
|
2070
|
|
|
|
|
|
|
For example, if "eval_elisp" is returning some messages to STDERR |
2071
|
|
|
|
|
|
|
that you'd rather filter out, you could do that in one of two ways: |
2072
|
|
|
|
|
|
|
|
2073
|
|
|
|
|
|
|
Changing the object-wide default: |
2074
|
|
|
|
|
|
|
|
2075
|
|
|
|
|
|
|
my $er = Emacs::Run->new( { redirector => 'stdout_only' } ); |
2076
|
|
|
|
|
|
|
my $result = $er->eval_elisp( $elisp_code ); |
2077
|
|
|
|
|
|
|
|
2078
|
|
|
|
|
|
|
Using an option specific to this method call: |
2079
|
|
|
|
|
|
|
|
2080
|
|
|
|
|
|
|
my $er = Emacs::Run->new(); |
2081
|
|
|
|
|
|
|
my $result = $er->eval_elisp( $elisp_code, { redirector => 'stdout_only' } ); |
2082
|
|
|
|
|
|
|
|
2083
|
|
|
|
|
|
|
If you need some behavior not supported by these redirector codes, |
2084
|
|
|
|
|
|
|
it is possible to use a Bourne-shell style redirect, like so: |
2085
|
|
|
|
|
|
|
|
2086
|
|
|
|
|
|
|
# return stdout only, but maintain an error log file |
2087
|
|
|
|
|
|
|
my $er = Emacs::Run->new( { shell_output_director => "2>$logfile" } ); |
2088
|
|
|
|
|
|
|
my $result = $er->eval_elisp( $elisp_code ); |
2089
|
|
|
|
|
|
|
|
2090
|
|
|
|
|
|
|
As with L, the L can be set |
2091
|
|
|
|
|
|
|
at the object-level or (often) at the method-level. |
2092
|
|
|
|
|
|
|
|
2093
|
|
|
|
|
|
|
=over |
2094
|
|
|
|
|
|
|
|
2095
|
|
|
|
|
|
|
=item shell_output_director |
2096
|
|
|
|
|
|
|
|
2097
|
|
|
|
|
|
|
The B (sometimes called B for short) is a |
2098
|
|
|
|
|
|
|
string appended to the internally generated emacs invocation commands to |
2099
|
|
|
|
|
|
|
control what happens to output. |
2100
|
|
|
|
|
|
|
|
2101
|
|
|
|
|
|
|
Typical values (on a unix-like system) are: |
2102
|
|
|
|
|
|
|
|
2103
|
|
|
|
|
|
|
=over |
2104
|
|
|
|
|
|
|
|
2105
|
|
|
|
|
|
|
=item '2>&1' |
2106
|
|
|
|
|
|
|
|
2107
|
|
|
|
|
|
|
Intermix STDOUT and STDERR (in elisp: both "message" and "print" |
2108
|
|
|
|
|
|
|
functions work). |
2109
|
|
|
|
|
|
|
|
2110
|
|
|
|
|
|
|
=item '2>/dev/null' |
2111
|
|
|
|
|
|
|
|
2112
|
|
|
|
|
|
|
return only STDOUT, throwing away STDERR (in elisp: get output |
2113
|
|
|
|
|
|
|
only from "print"). But see L's B. |
2114
|
|
|
|
|
|
|
|
2115
|
|
|
|
|
|
|
=item "> $file 2>&1" |
2116
|
|
|
|
|
|
|
|
2117
|
|
|
|
|
|
|
send all output to the file $file |
2118
|
|
|
|
|
|
|
|
2119
|
|
|
|
|
|
|
=item ">> $file 2>&1" |
2120
|
|
|
|
|
|
|
|
2121
|
|
|
|
|
|
|
append all output to the file $file, preserving any existing |
2122
|
|
|
|
|
|
|
content. |
2123
|
|
|
|
|
|
|
|
2124
|
|
|
|
|
|
|
=item "2 > $log_file" |
2125
|
|
|
|
|
|
|
|
2126
|
|
|
|
|
|
|
return only STDOUT, but save STDERR to $log_file |
2127
|
|
|
|
|
|
|
|
2128
|
|
|
|
|
|
|
=back |
2129
|
|
|
|
|
|
|
|
2130
|
|
|
|
|
|
|
=back |
2131
|
|
|
|
|
|
|
|
2132
|
|
|
|
|
|
|
=head1 internal documentation (how the code works, etc). |
2133
|
|
|
|
|
|
|
|
2134
|
|
|
|
|
|
|
=head2 internal attributes |
2135
|
|
|
|
|
|
|
|
2136
|
|
|
|
|
|
|
Object attributes intended largely for internal use. The client |
2137
|
|
|
|
|
|
|
programmer has access to these, but is not expected to need it. |
2138
|
|
|
|
|
|
|
Note: the common "leading underscore" naming convention is not used here. |
2139
|
|
|
|
|
|
|
|
2140
|
|
|
|
|
|
|
=over |
2141
|
|
|
|
|
|
|
|
2142
|
|
|
|
|
|
|
=item ec_lib_loader |
2143
|
|
|
|
|
|
|
|
2144
|
|
|
|
|
|
|
A fragment of an emacs command line invocation to load emacs libraries. |
2145
|
|
|
|
|
|
|
Different attributes exist to specify emacs libraries to be loaded: |
2146
|
|
|
|
|
|
|
as these are processed, the ec_lib_loader string gradually accumulates |
2147
|
|
|
|
|
|
|
code needed to load them (so that when need be, the process can use |
2148
|
|
|
|
|
|
|
the intermediate value of the ec_lib_loader to get the benefit of |
2149
|
|
|
|
|
|
|
the previously processed library specifications). |
2150
|
|
|
|
|
|
|
|
2151
|
|
|
|
|
|
|
The primary reason for this approach is that each library loaded |
2152
|
|
|
|
|
|
|
has the potential to modify the emacs load-path, which may be |
2153
|
|
|
|
|
|
|
key for the success of later load attempts. |
2154
|
|
|
|
|
|
|
|
2155
|
|
|
|
|
|
|
The process of probing for each library in one of the "requested" |
2156
|
|
|
|
|
|
|
lists has to be done in the context of all libraries that have been |
2157
|
|
|
|
|
|
|
previously found. Without some place to store intermediate results |
2158
|
|
|
|
|
|
|
in some form, this process might need to be programmed as one large |
2159
|
|
|
|
|
|
|
monolithic routine. |
2160
|
|
|
|
|
|
|
|
2161
|
|
|
|
|
|
|
=item lib_data_initial |
2162
|
|
|
|
|
|
|
|
2163
|
|
|
|
|
|
|
The initial setting of L when the object is instantiated. |
2164
|
|
|
|
|
|
|
As currently implemented, some operations here require resetting |
2165
|
|
|
|
|
|
|
the state of L and re-building it. This attribute |
2166
|
|
|
|
|
|
|
facilitates that process. |
2167
|
|
|
|
|
|
|
|
2168
|
|
|
|
|
|
|
=back |
2169
|
|
|
|
|
|
|
|
2170
|
|
|
|
|
|
|
=head2 Loaded vs. in load-path |
2171
|
|
|
|
|
|
|
|
2172
|
|
|
|
|
|
|
The emacs variable "load-path" behaves much like the shell's $PATH |
2173
|
|
|
|
|
|
|
(or perl's @INC): if you try to load a library called "dired", emacs |
2174
|
|
|
|
|
|
|
searches through the load-path in sequence, looking for an appropriately |
2175
|
|
|
|
|
|
|
named file (e.g. "dired.el"), it then evaluates it's contents, and |
2176
|
|
|
|
|
|
|
the features defined in the file become available for use. It is also possible |
2177
|
|
|
|
|
|
|
to load a file by telling emacs the path and filename, and that works |
2178
|
|
|
|
|
|
|
whether or not it is located in the load-path. |
2179
|
|
|
|
|
|
|
|
2180
|
|
|
|
|
|
|
There I at least a slight difference between the two, however. |
2181
|
|
|
|
|
|
|
For example, the present version of the "extract-docstrings.el" |
2182
|
|
|
|
|
|
|
library (see L) contains code like this, that |
2183
|
|
|
|
|
|
|
will break if the library you're looking for is not in the load-path: |
2184
|
|
|
|
|
|
|
|
2185
|
|
|
|
|
|
|
(setq codefile (locate-library library)) |
2186
|
|
|
|
|
|
|
|
2187
|
|
|
|
|
|
|
So some of the routines here (notably L) |
2188
|
|
|
|
|
|
|
generate elisp with an extra feature that adds the location of the file |
2189
|
|
|
|
|
|
|
to the load-path as well as just loading it. |
2190
|
|
|
|
|
|
|
|
2191
|
|
|
|
|
|
|
=head2 Interactive vs. Non-interactive Elisp Init |
2192
|
|
|
|
|
|
|
|
2193
|
|
|
|
|
|
|
Emacs::Run tries to use the user's normal emacs init process even |
2194
|
|
|
|
|
|
|
though it runs non-interactively. Unfortunately, it's possible that |
2195
|
|
|
|
|
|
|
the init files may need to be cleaned up in order to be used |
2196
|
|
|
|
|
|
|
non-interactively. In my case I found that I needed to check the |
2197
|
|
|
|
|
|
|
"x-no-window-manager" variable and selectively disable some code that |
2198
|
|
|
|
|
|
|
sets X fonts for me: |
2199
|
|
|
|
|
|
|
|
2200
|
|
|
|
|
|
|
;; We must do this check to allow "emacs --batch -l .emacs" to work |
2201
|
|
|
|
|
|
|
(unless (eq x-no-window-manager nil) |
2202
|
|
|
|
|
|
|
(zoom-set-font "-Misc-Fixed-Bold-R-Normal--15-140-75-75-C-90-ISO8859-1")) |
2203
|
|
|
|
|
|
|
|
2204
|
|
|
|
|
|
|
Alternately, L may be used to run elisp using a |
2205
|
|
|
|
|
|
|
full, externally spawned emacs, without using the --batch option: |
2206
|
|
|
|
|
|
|
you'll see another emacs window temporarily spring into life, and then |
2207
|
|
|
|
|
|
|
get destroyed, after passing the contents of the current-buffer back |
2208
|
|
|
|
|
|
|
by using a temporary file. |
2209
|
|
|
|
|
|
|
|
2210
|
|
|
|
|
|
|
=head2 INTERNALS |
2211
|
|
|
|
|
|
|
|
2212
|
|
|
|
|
|
|
=head3 The Tree of Method Calls |
2213
|
|
|
|
|
|
|
|
2214
|
|
|
|
|
|
|
The potential tree of method calls now runs fairly deep. A bug in a |
2215
|
|
|
|
|
|
|
primitive such as L can have wide-ranging effects: |
2216
|
|
|
|
|
|
|
|
2217
|
|
|
|
|
|
|
new |
2218
|
|
|
|
|
|
|
init |
2219
|
|
|
|
|
|
|
append_to_before_hook |
2220
|
|
|
|
|
|
|
process_emacs_libs_addition |
2221
|
|
|
|
|
|
|
set_up_ec_lib_loader |
2222
|
|
|
|
|
|
|
lib_or_file |
2223
|
|
|
|
|
|
|
genec_load_emacs_init |
2224
|
|
|
|
|
|
|
append_to_ec_lib_loader |
2225
|
|
|
|
|
|
|
detect_site_init |
2226
|
|
|
|
|
|
|
detect_lib |
2227
|
|
|
|
|
|
|
genec_loader_lib_needed |
2228
|
|
|
|
|
|
|
append_to_ec_lib_loader |
2229
|
|
|
|
|
|
|
genec_loader_file_needed |
2230
|
|
|
|
|
|
|
quote_elisp |
2231
|
|
|
|
|
|
|
elisp_to_load_file |
2232
|
|
|
|
|
|
|
append_to_ec_lib_loader |
2233
|
|
|
|
|
|
|
genec_loader_lib_requested |
2234
|
|
|
|
|
|
|
detect_lib |
2235
|
|
|
|
|
|
|
append_to_ec_lib_loader |
2236
|
|
|
|
|
|
|
genec_loader_file_requested |
2237
|
|
|
|
|
|
|
quote_elisp |
2238
|
|
|
|
|
|
|
elisp_to_load_file |
2239
|
|
|
|
|
|
|
append_to_ec_lib_loader |
2240
|
|
|
|
|
|
|
probe_emacs_version |
2241
|
|
|
|
|
|
|
parse_emacs_version_string |
2242
|
|
|
|
|
|
|
|
2243
|
|
|
|
|
|
|
|
2244
|
|
|
|
|
|
|
eval_elisp |
2245
|
|
|
|
|
|
|
quote_elisp |
2246
|
|
|
|
|
|
|
clean_return_value |
2247
|
|
|
|
|
|
|
set_up_ec_lib_loader |
2248
|
|
|
|
|
|
|
lib_or_file |
2249
|
|
|
|
|
|
|
genec_load_emacs_init |
2250
|
|
|
|
|
|
|
append_to_ec_lib_loader |
2251
|
|
|
|
|
|
|
find_dot_emacs |
2252
|
|
|
|
|
|
|
detect_site_init |
2253
|
|
|
|
|
|
|
detect_lib |
2254
|
|
|
|
|
|
|
genec_loader_lib_needed |
2255
|
|
|
|
|
|
|
append_to_ec_lib_loader |
2256
|
|
|
|
|
|
|
genec_loader_file_needed |
2257
|
|
|
|
|
|
|
quote_elisp |
2258
|
|
|
|
|
|
|
elisp_to_load_file |
2259
|
|
|
|
|
|
|
append_to_ec_lib_loader |
2260
|
|
|
|
|
|
|
genec_loader_lib_requested |
2261
|
|
|
|
|
|
|
detect_lib |
2262
|
|
|
|
|
|
|
append_to_ec_lib_loader |
2263
|
|
|
|
|
|
|
genec_loader_file_requested |
2264
|
|
|
|
|
|
|
quote_elisp |
2265
|
|
|
|
|
|
|
elisp_to_load_file |
2266
|
|
|
|
|
|
|
append_to_ec_lib_loader |
2267
|
|
|
|
|
|
|
|
2268
|
|
|
|
|
|
|
Note that as of this writing (version 0.09) this code ensures that |
2269
|
|
|
|
|
|
|
the L string is up-to-date by continually re-generating |
2270
|
|
|
|
|
|
|
it. |
2271
|
|
|
|
|
|
|
|
2272
|
|
|
|
|
|
|
=head1 TODO |
2273
|
|
|
|
|
|
|
|
2274
|
|
|
|
|
|
|
=over |
2275
|
|
|
|
|
|
|
|
2276
|
|
|
|
|
|
|
=item * |
2277
|
|
|
|
|
|
|
|
2278
|
|
|
|
|
|
|
Rather than use elisp's "print", should probably use "prin1" (does what |
2279
|
|
|
|
|
|
|
you mean without need for a clean-up routine). |
2280
|
|
|
|
|
|
|
|
2281
|
|
|
|
|
|
|
=item * |
2282
|
|
|
|
|
|
|
|
2283
|
|
|
|
|
|
|
Look into cache tricks (just Memoize?) to speed things up a |
2284
|
|
|
|
|
|
|
little. See L. |
2285
|
|
|
|
|
|
|
|
2286
|
|
|
|
|
|
|
=item * |
2287
|
|
|
|
|
|
|
|
2288
|
|
|
|
|
|
|
Have "new" fail (return undef) if emacs can not be |
2289
|
|
|
|
|
|
|
found on the system. This way you can use the result |
2290
|
|
|
|
|
|
|
of "new" to determine if you should skip tests, etc. |
2291
|
|
|
|
|
|
|
|
2292
|
|
|
|
|
|
|
=item * |
2293
|
|
|
|
|
|
|
|
2294
|
|
|
|
|
|
|
I suspect some quoting issues still lurk e.g. a library |
2295
|
|
|
|
|
|
|
filename containing a double-quote will probably crash things. |
2296
|
|
|
|
|
|
|
|
2297
|
|
|
|
|
|
|
=item * |
2298
|
|
|
|
|
|
|
|
2299
|
|
|
|
|
|
|
Add a method to match an emacs regexp against a string. See: |
2300
|
|
|
|
|
|
|
L |
2301
|
|
|
|
|
|
|
|
2302
|
|
|
|
|
|
|
(goto-char (point-min)) |
2303
|
|
|
|
|
|
|
(re-search-forward "$elisp_pattern") |
2304
|
|
|
|
|
|
|
(setq first_capture (match-string 1)) |
2305
|
|
|
|
|
|
|
|
2306
|
|
|
|
|
|
|
=item * |
2307
|
|
|
|
|
|
|
|
2308
|
|
|
|
|
|
|
In L, add support for skipping to a line number |
2309
|
|
|
|
|
|
|
after opening a file |
2310
|
|
|
|
|
|
|
|
2311
|
|
|
|
|
|
|
=item * |
2312
|
|
|
|
|
|
|
|
2313
|
|
|
|
|
|
|
I think this feature of emacs invocation could be used to simplify |
2314
|
|
|
|
|
|
|
things a little (I'm manipulating load-path directly at present): |
2315
|
|
|
|
|
|
|
|
2316
|
|
|
|
|
|
|
`-L DIR' |
2317
|
|
|
|
|
|
|
`--directory=DIR' |
2318
|
|
|
|
|
|
|
Add directory DIR to the variable `load-path'. |
2319
|
|
|
|
|
|
|
|
2320
|
|
|
|
|
|
|
=item * |
2321
|
|
|
|
|
|
|
|
2322
|
|
|
|
|
|
|
loop in eval_elisp_full_emacs needs to time-out (e.g. if no output is written) |
2323
|
|
|
|
|
|
|
|
2324
|
|
|
|
|
|
|
=item * |
2325
|
|
|
|
|
|
|
|
2326
|
|
|
|
|
|
|
Write an alternate to the eval_elisp_full_emacs that captures an |
2327
|
|
|
|
|
|
|
image of the external emacs process. (Allows automated tests of |
2328
|
|
|
|
|
|
|
syntax coloring, etc.) Can this be done portably? |
2329
|
|
|
|
|
|
|
|
2330
|
|
|
|
|
|
|
=item * |
2331
|
|
|
|
|
|
|
|
2332
|
|
|
|
|
|
|
Write more tests of redirectors -- found and fixed (?) bug in stderr_only. |
2333
|
|
|
|
|
|
|
|
2334
|
|
|
|
|
|
|
=back |
2335
|
|
|
|
|
|
|
|
2336
|
|
|
|
|
|
|
=head1 BUGS & LIMITATIONS |
2337
|
|
|
|
|
|
|
|
2338
|
|
|
|
|
|
|
=over |
2339
|
|
|
|
|
|
|
|
2340
|
|
|
|
|
|
|
=item * |
2341
|
|
|
|
|
|
|
|
2342
|
|
|
|
|
|
|
When an elisp library is marked as "needed", and it is not available, |
2343
|
|
|
|
|
|
|
failure occurs relatively late: it does not happen during object |
2344
|
|
|
|
|
|
|
instantiation, but waits until an attempted run with the object |
2345
|
|
|
|
|
|
|
(that is, on a call such as "$er->eval_elisp", not "Emacs::Run->new"). |
2346
|
|
|
|
|
|
|
|
2347
|
|
|
|
|
|
|
=item * |
2348
|
|
|
|
|
|
|
|
2349
|
|
|
|
|
|
|
This module was developed around Gnu emacs running on a |
2350
|
|
|
|
|
|
|
Gnu/linux platform. Some attempts have been made to make it's |
2351
|
|
|
|
|
|
|
use portable to other platforms. At present, using it with a |
2352
|
|
|
|
|
|
|
non-gnu emacs such as xemacs is not likely to work. |
2353
|
|
|
|
|
|
|
|
2354
|
|
|
|
|
|
|
=item * |
2355
|
|
|
|
|
|
|
|
2356
|
|
|
|
|
|
|
The L routine strips leading and trailing |
2357
|
|
|
|
|
|
|
newline-quote pairs, but that only covers the case of individual |
2358
|
|
|
|
|
|
|
elisp print functions. Evaluating elisp code with multiple |
2359
|
|
|
|
|
|
|
prints will need something fancier to clean up their behavior. |
2360
|
|
|
|
|
|
|
|
2361
|
|
|
|
|
|
|
=item * |
2362
|
|
|
|
|
|
|
|
2363
|
|
|
|
|
|
|
L runs into trouble if there's a bug in the .emacs |
2364
|
|
|
|
|
|
|
file, because it proceeds when it can find the file via |
2365
|
|
|
|
|
|
|
L, but doesn't verify it will load cleanly: |
2366
|
|
|
|
|
|
|
it charges ahead and tries to use it while doing a L, |
2367
|
|
|
|
|
|
|
which gets confused because it looks for a very specific message |
2368
|
|
|
|
|
|
|
to indicate failure, and doesn't understand any error messages from |
2369
|
|
|
|
|
|
|
an earlier stage. It would probably be better for L |
2370
|
|
|
|
|
|
|
to also vet the file, and error out if it doesn't succeed. |
2371
|
|
|
|
|
|
|
|
2372
|
|
|
|
|
|
|
=back |
2373
|
|
|
|
|
|
|
|
2374
|
|
|
|
|
|
|
=head1 SEE ALSO |
2375
|
|
|
|
|
|
|
|
2376
|
|
|
|
|
|
|
L |
2377
|
|
|
|
|
|
|
|
2378
|
|
|
|
|
|
|
Emacs Documentation: Command Line Arguments for Emacs Invocation |
2379
|
|
|
|
|
|
|
L |
2380
|
|
|
|
|
|
|
|
2381
|
|
|
|
|
|
|
A lightning talk about (among other things) using perl to test |
2382
|
|
|
|
|
|
|
emacs code: "Using perl to test non-perl code": |
2383
|
|
|
|
|
|
|
|
2384
|
|
|
|
|
|
|
L |
2385
|
|
|
|
|
|
|
|
2386
|
|
|
|
|
|
|
=head1 OTHER EXAMPLES |
2387
|
|
|
|
|
|
|
|
2388
|
|
|
|
|
|
|
Examples of "advanced" features (i.e. ones you're unlikely to want to use): |
2389
|
|
|
|
|
|
|
|
2390
|
|
|
|
|
|
|
# Specify in detail how the emacs lisp libraries should be loaded |
2391
|
|
|
|
|
|
|
# (initialization does not fail if a library that's merely "requested" |
2392
|
|
|
|
|
|
|
# is unavailable): |
2393
|
|
|
|
|
|
|
$lib_data = [ |
2394
|
|
|
|
|
|
|
[ 'dired', { type=>'lib', priority=>'needed' } ], |
2395
|
|
|
|
|
|
|
[ '/tmp/my-load-path.el', { type=>'file', priority=>'requested' } ], |
2396
|
|
|
|
|
|
|
[ '/tmp/my-elisp.el', { type=>'file', priority=>'needed' } ], |
2397
|
|
|
|
|
|
|
]; |
2398
|
|
|
|
|
|
|
my $er = Emacs::Run->new({ |
2399
|
|
|
|
|
|
|
lib_data => $lib_data, |
2400
|
|
|
|
|
|
|
}); |
2401
|
|
|
|
|
|
|
my $result = $er->eval_lisp( |
2402
|
|
|
|
|
|
|
qq{ (print (my-elisp-run-my-code "$perl_string")) } |
2403
|
|
|
|
|
|
|
); |
2404
|
|
|
|
|
|
|
|
2405
|
|
|
|
|
|
|
|
2406
|
|
|
|
|
|
|
|
2407
|
|
|
|
|
|
|
# using a "redirector" code (capture only stderr, ignore stdout, like '1>/dev/null') |
2408
|
|
|
|
|
|
|
$er = Emacs::Run->new({ |
2409
|
|
|
|
|
|
|
redirector => 'stderr_only' |
2410
|
|
|
|
|
|
|
}); |
2411
|
|
|
|
|
|
|
my $result = $er->eval_elisp( '(message "hello world") (print "you can't see me"))' ); |
2412
|
|
|
|
|
|
|
|
2413
|
|
|
|
|
|
|
|
2414
|
|
|
|
|
|
|
|
2415
|
|
|
|
|
|
|
# View your emacs load_path from the command-line |
2416
|
|
|
|
|
|
|
perl -MEmacs::Run -le'my $er=Emacs::Run->new; print for @{ $er->get_load_path }'; |
2417
|
|
|
|
|
|
|
|
2418
|
|
|
|
|
|
|
# Note that the obvious direct emacs invocation will not show .emacs customizations: |
2419
|
|
|
|
|
|
|
emacs --batch --eval "(print (mapconcat 'identity load-path \"\n\"))" |
2420
|
|
|
|
|
|
|
|
2421
|
|
|
|
|
|
|
# This does though |
2422
|
|
|
|
|
|
|
emacs --batch -l ~/.emacs --eval "(prin1 (mapconcat 'identity load-path \"\n\"))" 2>/dev/null |
2423
|
|
|
|
|
|
|
|
2424
|
|
|
|
|
|
|
|
2425
|
|
|
|
|
|
|
=head1 AUTHOR |
2426
|
|
|
|
|
|
|
|
2427
|
|
|
|
|
|
|
Joseph Brenner, Edoom@kzsu.stanford.eduE, |
2428
|
|
|
|
|
|
|
07 Mar 2008 |
2429
|
|
|
|
|
|
|
|
2430
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
2431
|
|
|
|
|
|
|
|
2432
|
|
|
|
|
|
|
Copyright (C) 2008 by Joseph Brenner |
2433
|
|
|
|
|
|
|
|
2434
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
2435
|
|
|
|
|
|
|
it under the same terms as Perl itself, either Perl version 5.8.2 or, |
2436
|
|
|
|
|
|
|
at your option, any later version of Perl 5 you may have available. |
2437
|
|
|
|
|
|
|
|
2438
|
|
|
|
|
|
|
|
2439
|
|
|
|
|
|
|
=cut |