File: ifeffit_shell.pl

package info (click to toggle)
horae 071~svn536-1
  • links: PTS
  • area: contrib
  • in suites: wheezy
  • size: 12,996 kB
  • sloc: perl: 67,215; lisp: 744; sh: 78; makefile: 76; ansic: 35
file content (345 lines) | stat: -rwxr-xr-x 11,695 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
#!/usr/bin/perl -w
# Simple shell for ifeffit in perl
use lib '/usr/local/share/ifeffit/perl';
use vars qw($Escape $Prompt $HOME);
use subs qw(ShowHist ShowCommands END HELP IfeffitHelp);
use Getopt::Std;
getopts('xq');

#---------------------------------------------------
#  variables the user may want to customize are
#  initialized before reading .ifeffitrc.
$HOME             = $ENV{HOME};
$RCFile           = "$HOME/.ifeffitrc";
$Escape           = "!";
$Prompt_main      = "Ifeffit>";
$Prompt_more      = "  ...  >";
$history_file     = "$HOME/.ifeffit_hist";
$history_lines    = 500;
@shell_commands   = qw(cd cp mv ls rm mkdir rmdir more cat pwd vi);
@ifeffit_commands = qw(plot newplot spline show fftf fftr load print
		       pre_edge read_data write_data exit quit ff2chi
		       zoom cursor help minimize set macro);
%IF_coms=(
	  "plot"       => "general 2-d plot ",
	  "newplot"    => "general 2-d plot, after clearing plot screen ",
	  "spline"     => "XAFS background removal, ala autobk ",
	  "show"       => "display scalar, array, or text Program Variables ",
	  "print"      => "print value of scalar or array variable or expression",
	  "fftf"       => "forward (k->R) XAFS Fourier transform ",
	  "fftr"       => "reverse (R->k) XAFS Fourier transform ",
	  "load"       => "execute a file of Ifeffit commands ",
	  "pre_edge"   => "determine e0, pre-edge line, and edge jump of xmu data",
	  "read_data"  => "read arrays from data file ",
	  "write_data" => "write arrays and text strings to data file ",
	  "exit"       => "leave Ifeffit ",
	  "quit"       => "leave Ifeffit ",
	  "ff2chi"     => "combine feff paths to give k and chi arrays ",
	  "zoom"       => "pick window on plot screen with mouse ",
	  "cursor"     => "pick x-y coordinates on plot screen with mouse ",
	  "minimize"   => "generalized least-squares fit ",
	  "set"        => "define a scalar, array, or text Program Variable ",
	  "macro"      => "define an ifeffit macro");

#---------------------------------------------------
# load needed perl modules
$,=" ";  $|=1 ;


#---------------------------------------------------
# load needed perl modules
$,=" ";  $|=1 ;

# make sure we can use ifeffit module
print "  Ifeffit";
eval "use Ifeffit";
if ($Ifeffit::VERSION) {
    ifeffit("print \$&build");
    print "  Ifeffit Shell  Perl Module $Ifeffit::VERSION ";
} else {
    die "Perl Module not installed properly\n";
}
# readline module
eval "use Term::ReadLine"; my $does_readline = ($@ eq "");
unless ($opt_q) {
    print $does_readline ? "(ReadLine enabled) " : "(No ReadLine) " ;
}
print "\n";
#-------------------------------------
# load startup files, then files listed on command line
if ($opt_x) {
    print "no configuration file loaded \n" unless ($opt_q);
} elsif ( -e $RCFile ) {
    print "  reading $RCFile ... " unless ($opt_q);
    eval 'require "$RCFile"';
    unless ($opt_q) {($@ eq "") ? print " OK\n": print "problem\n"; }
}
my $retval = 0;
foreach my $f (@ARGV) {
    print "  loading $f ..."  unless ($opt_q);
    $retval = ifeffit("load $f\n");
    unless ($opt_q) { ($retval==0) ? print " OK\n" : print " problem!\n";}
}

my $shellcoms = join ("|", @shell_commands ); # used below in regex match
#-------------------------------------
#  set up readline stuff
if ($does_readline) {
    $term = new Term::ReadLine 'ifeffit', \*STDIN, \*STDOUT ;
    $term->ornaments(1);
# read in history from last session
    if ((-e "$history_file")&& (open HIST, "<$history_file")) {
	my @allhist = <HIST>;
	close HIST;
	map s/\n//g , @allhist ;
	foreach (@allhist) {  $term->addhistory($_); }
    }
# set completion model: shell_commands and ifeffit_commands
#                       for 1st word, filenames for rest of line
    my $attribs = $term->Attribs;
    $attribs->{attempted_completion_function} = sub {
	my ($text, $line, $start, $end) = @_;
	if ((substr($line, 0, $start) =~ /^\s*$/) or
	    (substr($line, 0, $start) =~ /^help/i) ) {
	    $attribs->{completion_entry_function} = $attribs->{'list_completion_function'};
	    $attribs->{completion_word} = [@shell_commands, @ifeffit_commands];
	    return $term->completion_matches($text, $attribs->{'completion_entry_function'});
	} else {
	    $attribs->{completion_entry_function} = $attribs->{'filename_completion_function'};
	    return ();
	}
    }
}
#
# determine prompt and reading mechanism
if ($does_readline) {          # use readline if available
    $getline = sub { my $p = shift;
		     my $j = $term->readline($p);
		     $j = "__NULL_\n\n" unless $j;
		     chomp $j; $j =~ s|~|$ENV{"HOME"}| ; return $j; };
} else {                       # or use simple read
    $getline = sub { my $p = shift;
		     print "$p"; my $j = <>;
		     $j = "__NULL_\n\n" unless $j;
		     chomp $j; $j =~ s|~|$ENV{"HOME"}| ; return $j; };
}
#-------------------------------------

##  main loop
my ($line, $prom, @args);
if ($opt_x) {$line += $opt_x};
while (1) {
    $prom = ($retval == -1) ? $Prompt_more : $Prompt_main; # decide prompt
    $_ = &$getline($prom);         # prompt for line
    next if ((/^\s*$/) or (/^__NULL/));
    process_command($_) if ($_);
}
## done
#-------------------------------------
sub process_command{
    $line = $_ = shift;
    @args = split();          #
    $_    = lc(shift(@args));      # simplifies the matching below
# execute:                         # based on first word (now in $_)
    exit if (/^quit$/o or /^exit$/o);
    if (/^\?$/o or /^help$/o) { Help($line); }
    elsif (/^\?\?$/o)         { ShowCommands;}
    elsif (/^l$/o)            { ShowHist(@args); }
    elsif (/^cd$/o)           { chdir("@args"); }
    elsif (/^rm$/o)           { unlink("@args"); }
    elsif (/^perl$/o)         { eval("@args"); }
    elsif (/^($shellcoms)$/)  { system("$line"); }
    elsif (/^$Escape/)        { system(substr("$line",1)); }
    else {
	$line =~ s|~|$ENV{"HOME"}| if (/^load$/o or /^read/o or /^write/o);
	$retval = ifeffit("$line\n");
    }
}
sub ShowHist {  # use 'l' to show command history
    if ($does_readline) {
	my $n = $#_ > -1 ? shift : 10;
	my @h = $term->GetHistory();
	my $min = $#h < $n-1 ? 0 : $#h-$n+1;
	map {print "$_: $h[$_]\n"} ($min..$#h);
    }
}

sub ShowCommands {
    print "Ifeffit is aware of these shell commands:\n ";
    my $i = 0;
    foreach my $t (@shell_commands) {
	 print " $t";
	 $i  += 1 + length($t);
	 if ($i > 60) {print "\n "; $i  = 0;}
     }
    print "\n" unless ($i ==  0);
}

sub Help {
    @args = split(/\s+/, $_[0]);
    if ($#args < 1) {  #    general help from pod
	print "Help is on the way ...\n";
	system ("perldoc $0\n");
    } else {
	shift @args;
	foreach my $t (@args) {IfeffitHelp($t);}
    }
}

sub END {  # executed at 'exit'
    # save history in history file
    if ($does_readline) {
	my @a= $term->GetHistory() if $term->can('GetHistory');
	$#a-- if $a[-1] =~ (/^\s*(quit|exit)\s*$/); # don't save the exit command!
	@a= @a[($#a-$history_lines+1)..($#a)] if $#a > $history_lines;
	if (open HIST, ">$history_file" ) {
	    print HIST join("\n",@a);
	    close HIST;
	} else {
	    print "Can't open $history_file\n";
	}
    }
    ##print "\tHave a nice day\n" unless ($opt_q);
}

sub IfeffitHelp {
    my $t = shift;
    my ($s) = ("unknown command (may be a shell command)");
    print " $t: ";
    foreach my $k  (keys %IF_coms) {
	if ($k eq $t) { $s = $IF_coms{$k};}
    }
    print " $s\n";
}


__END__

=head1 NAME

ifeffit - Shell Interface to IFEFFIT

=head1 SYNOPSIS

B<ifeffit> is a shell interface to the Ifeffit XAFS Analysis System.
Ifeffit commands are entered and executed as they are typed in, giving
complete access to the Ifeffit library in a relatively friendly
command-line program.

A sample session might look like this:

 %~>ifeffit
   Ifeffit  1.0004  Copyright (c) 2000 Matt Newville, Univ of Chicago
   Ifeffit Shell  Perl Module 1.2 (ReadLine enabled)
   reading /home/newville/.ifeffitrc ... OK
 Ifeffit> read_data(My.xmu,type=xmu)
 Ifeffit> spline(energy,xmu, rbkg = 1.0, kweight =1 )
 Ifeffit> plot(energy, xmu)
 Ifeffit> plot(energy, bkg)

=head1 DESCRIPTION

If you have the Perl module for the ReadLine library (Term::ReadLine and
Term::Readkeys are both required), you can use the command-line editing
features of the Gnu ReadLine library.  Most importantly, this library makes
the up arrow scroll through previous commands.  It also gives you access to
the last 300 commands typed in (stored in the file F<.ifeffit_hist> in your
home directory) in previous sessions.  The command C<l [number]> shows you
the last C<number> commands typed in.

There is also some support for command-line completion via the tab key.
While typing the first word at the command-line prompt, selected ifeffit
commands and shell commands will be 'tab-completed', meaning that hitting
the tab key will complete as much of a partially-typed command as possible.
The list of ifeffit and shell commands recognized for this purpose is
customizable.  After the first word has been fully typed, the tab key will
complete file names in the current working directory.

e.g.:

  %~>ifeffit
    Ifeffit  1.0002  Copyright (c) 2000 Matt Newville, Univ of Chicago
    Ifeffit Shell  Perl Module 1.2 (ReadLine enabled)
    reading /home/newville/.ifeffitrc ... OK
  Ifeffit>

=over 4

=item 1.

'quit' and 'exit' will exit the program.

'l' lists the history buffer

'?'  is an alias for help, which will display this document, or give a
     brief command summary  (as in: 'help plot').

'??' lists the known system shell commands that can be executed from
     within ifeffit.  For other shell commands, use the '!' character
     to escape to the system shell.

=item 2.

The resource file F<~/.ifeffitrc> (if found) is read at start-up to allow
customizations.  This file is read as a B<perl> script (not as raw ifeffit
commands).  To allow further confusion (err, customization), you can load
files of ifeffit commands at startup -- I<ifeffit myfile> will load the
file F<myfile> at start-up, as if you typed 'load myfile' at the
command-line.  This loading occurs after the F<~/.ifeffitrc> file is read,
which can provide a convenient way to override default macro definitions.

=item 3.

Shell variables: (can be customized in F<~/.ifeffitrc>)

$Escape  [default = '!']  a line starting with this character is sent
to the shell.

$Prompt  [default = 'Ifeffit> ']  command-line prompt.

$HOME    [default from Environment Variable] users home directory.

=item 4.

A useful procedure for developing and testing ifeffit scripts is

    ifeffit> ! emacs script &
              -- add ifeffit code to script and save the file
    ifeffit> load script

=back

=head1 CUSTOMIZATION

A typical ~/.ifeffitrc file might look like this:

   #
   # start-up perl for shiffit
     push @shell_commands, qw(emacs grep gunzip diff);
   #
   # pre-load some common ifeffit macros
     ifeffit("load $HOME/.ifeffit_macros ");

This file is "require'd" by I<ifeffit>.  The "push" line, adds a few more
commands to the default list of shell commands.  The "ifeffit" line loads
a bunch of pre-defined ifeffit macros.

=head1 AUTHOR

Matthew Newville  --  newville@cars.uchicago.edu

=head1 SEE ALSO

I<Term::Readline> perl module to use the GNU Readline library to improve
reading the command-line and enabling history mechanism.  This module is
available from Comprehensive Perl Archive Network.

I<Ifeffit.pm> perl module to use the Ifeffit XAFS Analysis library from
within perl.  Several applications distributed as part of the Ifeffit
Analysis System, including this program, requires this Ifeffit perl module,

I<Ifeffit Reference Manual> main reference for the commands of the Ifeffit
XAFS Analysis system.


=cut