GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-hist.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 /*
24 
25 The functions listed below were adapted from similar functions from
26 GNU Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991 Free
27 Software Foundation, Inc.
28 
29  do_history edit_history_readline
30  do_edit_history edit_history_add_hist
31 
32 */
33 
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37 
38 #include <cstdlib>
39 #include <cstring>
40 
41 #include <string>
42 
43 #include <fstream>
44 
45 #include <sys/types.h>
46 #include <unistd.h>
47 
48 #include "cmd-hist.h"
49 #include "file-ops.h"
50 #include "lo-mappers.h"
51 #include "octave-link.h"
52 #include "oct-env.h"
53 #include "oct-time.h"
54 #include "str-vec.h"
55 
56 #include <defaults.h>
57 #include "defun.h"
58 #include "error.h"
59 #include "gripes.h"
60 #include "input.h"
61 #include "oct-hist.h"
62 #include "oct-obj.h"
63 #include "pager.h"
64 #include "parse.h"
65 #include "sighandlers.h"
66 #include "sysdep.h"
67 #include "toplev.h"
68 #include "unwind-prot.h"
69 #include "utils.h"
70 #include "variables.h"
71 
72 // TRUE means input is coming from temporary history file.
74 
75 static std::string
77 {
78  std::string file;
79 
80  std::string env_file = octave_env::getenv ("OCTAVE_HISTFILE");
81 
82  if (! env_file.empty ())
83  file = env_file;
84 
85  if (file.empty ())
87  ".octave_hist");
88 
89  return file;
90 }
91 
92 static int
94 {
95  int size = 1000;
96 
97  std::string env_size = octave_env::getenv ("OCTAVE_HISTSIZE");
98 
99  if (! env_size.empty ())
100  {
101  int val;
102 
103  if (sscanf (env_size.c_str (), "%d", &val) == 1)
104  size = val > 0 ? val : 0;
105  }
106 
107  return size;
108 }
109 
110 static std::string
112 {
113  return
114  std::string ("# Octave " OCTAVE_VERSION ", %a %b %d %H:%M:%S %Y %Z <")
116  + std::string ("@")
118  + std::string (">");
119 }
120 
121 // The format of the timestamp marker written to the history file when
122 // Octave exits.
123 static std::string Vhistory_timestamp_format_string
125 
126 // Display, save, or load history. Stolen and modified from bash.
127 //
128 // Arg of -w FILENAME means write file, arg of -r FILENAME
129 // means read file, arg of -q means don't number lines. Arg of N
130 // means only display that many items.
131 
132 static string_vector
133 do_history (const octave_value_list& args, int nargout)
134 {
135  bool numbered_output = nargout == 0;
136 
137  unwind_protect frame;
138 
139  string_vector hlist;
140 
142 
143  int nargin = args.length ();
144 
145  // Number of history lines to show (-1 = all)
146  int limit = -1;
147 
148  for (octave_idx_type i = 0; i < nargin; i++)
149  {
150  octave_value arg = args(i);
151 
152  std::string option;
153 
154  if (arg.is_string ())
155  option = arg.string_value ();
156  else if (arg.is_numeric_type ())
157  {
158  limit = arg.int_value ();
159  if (limit < 0)
160  limit = -limit;
161  continue;
162  }
163  else
164  {
165  gripe_wrong_type_arg ("history", arg);
166  return hlist;
167  }
168 
169  if (option == "-r" || option == "-w" || option == "-a"
170  || option == "-n")
171  {
172  if (i < nargin - 1)
173  {
174  if (args(i+1).is_string ())
175  command_history::set_file (args(++i).string_value ());
176  else
177  {
178  error ("history: expecting file name for %s option",
179  option.c_str ());
180  return hlist;
181  }
182  }
183  else
185 
186  if (option == "-a")
187  // Append 'new' lines to file.
189 
190  else if (option == "-w")
191  // Write entire history.
193 
194  else if (option == "-r")
195  {
196  // Read entire file.
199  }
200 
201  else if (option == "-n")
202  {
203  // Read 'new' history from file.
206  }
207 
208  else
209  panic_impossible ();
210 
211  return hlist;
212  }
213  else if (option == "-c")
214  {
217  }
218  else if (option == "-q")
219  numbered_output = false;
220  else if (option == "--")
221  {
222  i++;
223  break;
224  }
225  else
226  {
227  // The last argument found in the command list that looks like
228  // an integer will be used
229  int tmp;
230 
231  if (sscanf (option.c_str (), "%d", &tmp) == 1)
232  {
233  if (tmp > 0)
234  limit = tmp;
235  else
236  limit = -tmp;
237  }
238 
239  else
240  {
241  if (option.length () > 0 && option[0] == '-')
242  error ("history: unrecognized option '%s'", option.c_str ());
243  else
244  error ("history: bad non-numeric arg '%s'", option.c_str ());
245 
246  return hlist;
247  }
248  }
249  }
250 
251  hlist = command_history::list (limit, numbered_output);
252 
253  int len = hlist.length ();
254 
255  if (nargout == 0)
256  {
257  for (octave_idx_type i = 0; i < len; i++)
258  octave_stdout << hlist[i] << "\n";
259  }
260 
261  return hlist;
262 }
263 
264 // Read the edited history lines from STREAM and return them
265 // one at a time. This can read unlimited length lines. The
266 // caller should free the storage.
267 
268 static char *
269 edit_history_readline (std::fstream& stream)
270 {
271  char c;
272  int line_len = 128;
273  int lindex = 0;
274  char *line = new char [line_len];
275  line[0] = '\0';
276 
277  while (stream.get (c))
278  {
279  if (lindex + 2 >= line_len)
280  {
281  char *tmp_line = new char [line_len += 128];
282  strcpy (tmp_line, line);
283  delete [] line;
284  line = tmp_line;
285  }
286 
287  if (c == '\n')
288  {
289  line[lindex++] = '\n';
290  line[lindex++] = '\0';
291  return line;
292  }
293  else
294  line[lindex++] = c;
295  }
296 
297  if (! lindex)
298  {
299  delete [] line;
300  return 0;
301  }
302 
303  if (lindex + 2 >= line_len)
304  {
305  char *tmp_line = new char [lindex+3];
306  strcpy (tmp_line, line);
307  delete [] line;
308  line = tmp_line;
309  }
310 
311  // Finish with newline if none in file.
312 
313  line[lindex++] = '\n';
314  line[lindex++] = '\0';
315  return line;
316 }
317 
318 static void
319 edit_history_add_hist (const std::string& line)
320 {
321  if (! line.empty ())
322  {
323  std::string tmp = line;
324 
325  int len = tmp.length ();
326 
327  if (len > 0 && tmp[len-1] == '\n')
328  tmp.resize (len - 1);
329 
330  if (! tmp.empty ())
331  if (command_history::add (tmp))
333  }
334 }
335 
336 static bool
337 get_int_arg (const octave_value& arg, int& val)
338 {
339  bool ok = true;
340 
341  if (arg.is_string ())
342  {
343  std::string tmp = arg.string_value ();
344 
345  ok = sscanf (tmp.c_str (), "%d", &val) == 1;
346  }
347  else if (arg.is_numeric_type ())
348  val = arg.int_value ();
349  else
350  ok = false;
351 
352  return ok;
353 }
354 
355 static std::string
357  bool insert_curr, const char *warn_for)
358 {
359  std::string retval;
360 
362 
363  int hist_count = hlist.length () - 1; // switch to zero-based indexing
364 
365  // The current command line is already part of the history list by
366  // the time we get to this point. Delete the cmd from the list when
367  // executing 'edit_history' so that it doesn't show up in the history
368  // but the actual commands performed will.
369 
370  if (! insert_curr)
371  command_history::remove (hist_count);
372 
373  hist_count--; // skip last entry in history list
374 
375  // If no numbers have been specified, the default is to edit the
376  // last command in the history list.
377 
378  int hist_beg = hist_count;
379  int hist_end = hist_count;
380 
381  bool reverse = false;
382 
383  // Process options.
384 
385  int nargin = args.length ();
386 
387  bool usage_error = false;
388  if (nargin == 2)
389  {
390  if (get_int_arg (args(0), hist_beg)
391  && get_int_arg (args(1), hist_end))
392  {
393  if (hist_beg < 0)
394  hist_beg += (hist_count + 1);
395  else
396  hist_beg--;
397  if (hist_end < 0)
398  hist_end += (hist_count + 1);
399  else
400  hist_end--;
401  }
402  else
403  usage_error = true;
404  }
405  else if (nargin == 1)
406  {
407  if (get_int_arg (args(0), hist_beg))
408  {
409  if (hist_beg < 0)
410  hist_beg += (hist_count + 1);
411  else
412  hist_beg--;
413  hist_end = hist_beg;
414  }
415  else
416  usage_error = true;
417  }
418 
419  if (usage_error)
420  {
421  usage ("%s [first] [last]", warn_for);
422  return retval;
423  }
424 
425  if (hist_beg > hist_count || hist_end > hist_count)
426  {
427  error ("%s: history specification out of range", warn_for);
428  return retval;
429  }
430 
431  if (hist_end < hist_beg)
432  {
433  std::swap (hist_end, hist_beg);
434  reverse = true;
435  }
436 
437  std::string name = octave_tempnam ("", "oct-");
438 
439  std::fstream file (name.c_str (), std::ios::out);
440 
441  if (! file)
442  {
443  error ("%s: couldn't open temporary file '%s'", warn_for,
444  name.c_str ());
445  return retval;
446  }
447 
448  if (reverse)
449  {
450  for (int i = hist_end; i >= hist_beg; i--)
451  file << hlist[i] << "\n";
452  }
453  else
454  {
455  for (int i = hist_beg; i <= hist_end; i++)
456  file << hlist[i] << "\n";
457  }
458 
459  file.close ();
460 
461  return name;
462 }
463 
464 static void
465 unlink_cleanup (const char *file)
466 {
467  gnulib::unlink (file);
468 }
469 
470 static void
472 {
473  std::string name = mk_tmp_hist_file (args, false, "edit_history");
474 
475  if (name.empty ())
476  return;
477 
478  // Call up our favorite editor on the file of commands.
479 
480  std::string cmd = VEDITOR;
481  cmd.append (" \"" + name + "\"");
482 
483  // Ignore interrupts while we are off editing commands. Should we
484  // maybe avoid using system()?
485 
486  volatile octave_interrupt_handler old_interrupt_handler
488 
489  int status = system (cmd.c_str ());
490 
491  octave_set_interrupt_handler (old_interrupt_handler);
492 
493  // Check if text edition was successfull. Abort the operation
494  // in case of failure.
495  if (status != EXIT_SUCCESS)
496  {
497  error ("edit_history: text editor command failed");
498  return;
499  }
500 
501  // Write the commands to the history file since source_file
502  // disables command line history while it executes.
503 
504  std::fstream file (name.c_str (), std::ios::in);
505 
506  char *line;
507  //int first = 1;
508  while ((line = edit_history_readline (file)) != 0)
509  {
510  // Skip blank lines.
511 
512  if (line[0] == '\n')
513  {
514  delete [] line;
515  continue;
516  }
517 
518  edit_history_add_hist (line);
519 
520  delete [] line;
521  }
522 
523  file.close ();
524 
525  // Turn on command echo, so the output from this will make better
526  // sense.
527 
528  unwind_protect frame;
529 
530  frame.add_fcn (unlink_cleanup, name.c_str ());
533 
536 
537  source_file (name);
538 }
539 
540 static void
542 {
543  std::string name = mk_tmp_hist_file (args, false, "run_history");
544 
545  if (name.empty ())
546  return;
547 
548  // Turn on command echo so the output from this will make better sense.
549 
550  unwind_protect frame;
551 
552  frame.add_fcn (unlink_cleanup, name.c_str ());
555 
558 
559  source_file (name);
560 }
561 
562 void
564 {
565  command_history::initialize (read_history_file,
568  octave_env::getenv ("OCTAVE_HISTCONTROL"));
569 
571 }
572 
573 void
575 {
576  octave_localtime now;
577 
578  std::string timestamp = now.strftime (Vhistory_timestamp_format_string);
579 
580  if (! timestamp.empty ())
581  if (command_history::add (timestamp))
582  octave_link::append_history (timestamp);
583 }
584 
585 DEFUN (edit_history, args, ,
586  "-*- texinfo -*-\n\
587 @deftypefn {Command} {} edit_history\n\
588 @deftypefnx {Command} {} edit_history @var{cmd_number}\n\
589 @deftypefnx {Command} {} edit_history @var{first} @var{last}\n\
590 Edit the history list using the editor named by the variable\n\
591 @w{@env{EDITOR}}.\n\
592 \n\
593 The commands to be edited are first copied to a temporary file. When you\n\
594 exit the editor, Octave executes the commands that remain in the file. It\n\
595 is often more convenient to use @code{edit_history} to define functions\n\
596 rather than attempting to enter them directly on the command line.\n\
597 The block of commands is executed as soon as you exit the editor.\n\
598 To avoid executing any commands, simply delete all the lines from the buffer\n\
599 before leaving the editor.\n\
600 \n\
601 When invoked with no arguments, edit the previously executed command;\n\
602 With one argument, edit the specified command @var{cmd_number};\n\
603 With two arguments, edit the list of commands between @var{first} and\n\
604 @var{last}. Command number specifiers may also be negative where -1\n\
605 refers to the most recently executed command.\n\
606 The following are equivalent and edit the most recently executed command.\n\
607 \n\
608 @example\n\
609 @group\n\
610 edit_history\n\
611 edit_history -1\n\
612 @end group\n\
613 @end example\n\
614 \n\
615 When using ranges, specifying a larger number for the first command than the\n\
616 last command reverses the list of commands before they are placed in the\n\
617 buffer to be edited.\n\
618 @seealso{run_history}\n\
619 @end deftypefn")
620 {
621  octave_value_list retval;
622 
623  do_edit_history (args);
624 
625  return retval;
626 }
627 
628 DEFUN (history, args, nargout,
629  "-*- texinfo -*-\n\
630 @deftypefn {Command} {} history\n\
631 @deftypefnx {Command} {} history @var{opt1} @dots{}\n\
632 @deftypefnx {Built-in Function} {@var{h} =} history ()\n\
633 @deftypefnx {Built-in Function} {@var{h} =} history (@var{opt1}, @dots{})\n\
634 If invoked with no arguments, @code{history} displays a list of commands\n\
635 that you have executed. Valid options are:\n\
636 \n\
637 @table @code\n\
638 @item @var{n}\n\
639 @itemx -@var{n}\n\
640 Display only the most recent @var{n} lines of history.\n\
641 \n\
642 @item -c\n\
643 Clear the history list.\n\
644 \n\
645 @item -q\n\
646 Don't number the displayed lines of history. This is useful for cutting\n\
647 and pasting commands using the X Window System.\n\
648 \n\
649 @item -r @var{file}\n\
650 Read the file @var{file}, appending its contents to the current\n\
651 history list. If the name is omitted, use the default history file\n\
652 (normally @file{~/.octave_hist}).\n\
653 \n\
654 @item -w @var{file}\n\
655 Write the current history to the file @var{file}. If the name is\n\
656 omitted, use the default history file (normally @file{~/.octave_hist}).\n\
657 @end table\n\
658 \n\
659 For example, to display the five most recent commands that you have\n\
660 typed without displaying line numbers, use the command\n\
661 @kbd{history -q 5}.\n\
662 \n\
663 If invoked with a single output argument, the history will be saved to that\n\
664 argument as a cell string and will not be output to screen.\n\
665 @end deftypefn")
666 {
667  octave_value retval;
668 
669  string_vector hlist = do_history (args, nargout);
670 
671  if (nargout > 0)
672  retval = Cell (hlist);
673 
674  return retval;
675 }
676 
677 DEFUN (run_history, args, ,
678  "-*- texinfo -*-\n\
679 @deftypefn {Command} {} run_history\n\
680 @deftypefnx {Command} {} run_history @var{cmd_number}\n\
681 @deftypefnx {Command} {} run_history @var{first} @var{last}\n\
682 Run commands from the history list.\n\
683 \n\
684 When invoked with no arguments, run the previously executed command;\n\
685 With one argument, run the specified command @var{cmd_number};\n\
686 With two arguments, run the list of commands between @var{first} and\n\
687 @var{last}. Command number specifiers may also be negative where -1\n\
688 refers to the most recently executed command.\n\
689 For example, the command\n\
690 \n\
691 @example\n\
692 @group\n\
693 run_history\n\
694  OR\n\
695 run_history -1\n\
696 @end group\n\
697 @end example\n\
698 \n\
699 @noindent\n\
700 executes the most recent command again.\n\
701 The command\n\
702 \n\
703 @example\n\
704 run_history 13 169\n\
705 @end example\n\
706 \n\
707 @noindent\n\
708 executes commands 13 through 169.\n\
709 \n\
710 Specifying a larger number for the first command than the last command\n\
711 reverses the list of commands before executing them.\n\
712 For example:\n\
713 \n\
714 @example\n\
715 @group\n\
716 disp (1)\n\
717 disp (2)\n\
718 run_history -1 -2\n\
719 @result{}\n\
720  2\n\
721  1\n\
722 @end group\n\
723 @end example\n\
724 \n\
725 @seealso{edit_history}\n\
726 @end deftypefn")
727 {
728  octave_value_list retval;
729 
730  do_run_history (args);
731 
732  return retval;
733 }
734 
735 DEFUN (history_control, args, nargout,
736  "-*- texinfo -*-\n\
737 @deftypefn {Built-in Function} {@var{val} =} history_control ()\n\
738 @deftypefnx {Built-in Function} {@var{old_val} =} history_control (@var{new_val})\n\
739 Query or set the internal variable that specifies how commands are saved\n\
740 to the history list. The default value is an empty character string,\n\
741 but may be overridden by the environment variable\n\
742 @w{@env{OCTAVE_HISTCONTROL}}.\n\
743 \n\
744 The value of @code{history_control} is a colon-separated list of values\n\
745 controlling how commands are saved on the history list. If the list\n\
746 of values includes @code{ignorespace}, lines which begin with a space\n\
747 character are not saved in the history list. A value of @code{ignoredups}\n\
748 causes lines matching the previous history entry to not be saved.\n\
749 A value of @code{ignoreboth} is shorthand for @code{ignorespace} and\n\
750 @code{ignoredups}. A value of @code{erasedups} causes all previous lines\n\
751 matching the current line to be removed from the history list before that\n\
752 line is saved. Any value not in the above list is ignored. If\n\
753 @code{history_control} is the empty string, all commands are saved on\n\
754 the history list, subject to the value of @code{history_save}.\n\
755 @seealso{history_file, history_size, history_timestamp_format_string, history_save}\n\
756 @end deftypefn")
757 {
758  octave_value retval;
759 
760  std::string old_history_control = command_history::histcontrol ();
761 
762  std::string tmp = old_history_control;
763 
764  retval = set_internal_variable (tmp, args, nargout, "history_control");
765 
766  if (tmp != old_history_control)
768 
769  return retval;
770 }
771 
772 DEFUN (history_size, args, nargout,
773  "-*- texinfo -*-\n\
774 @deftypefn {Built-in Function} {@var{val} =} history_size ()\n\
775 @deftypefnx {Built-in Function} {@var{old_val} =} history_size (@var{new_val})\n\
776 Query or set the internal variable that specifies how many entries\n\
777 to store in the history file. The default value is @code{1000},\n\
778 but may be overridden by the environment variable @w{@env{OCTAVE_HISTSIZE}}.\n\
779 @seealso{history_file, history_timestamp_format_string, history_save}\n\
780 @end deftypefn")
781 {
782  octave_value retval;
783 
784  int old_history_size = command_history::size ();
785 
786  int tmp = old_history_size;
787 
788  retval = set_internal_variable (tmp, args, nargout,
789  "history_size", -1,
791 
792  if (tmp != old_history_size)
794 
795  return retval;
796 }
797 
798 DEFUN (history_file, args, nargout,
799  "-*- texinfo -*-\n\
800 @deftypefn {Built-in Function} {@var{val} =} history_file ()\n\
801 @deftypefnx {Built-in Function} {@var{old_val} =} history_file (@var{new_val})\n\
802 Query or set the internal variable that specifies the name of the\n\
803 file used to store command history. The default value is\n\
804 @file{~/.octave_hist}, but may be overridden by the environment\n\
805 variable @w{@env{OCTAVE_HISTFILE}}.\n\
806 @seealso{history_size, history_save, history_timestamp_format_string}\n\
807 @end deftypefn")
808 {
809  octave_value retval;
810 
811  std::string old_history_file = command_history::file ();
812 
813  std::string tmp = old_history_file;
814 
815  retval = set_internal_variable (tmp, args, nargout, "history_file");
816 
817  if (tmp != old_history_file)
819 
820  return retval;
821 }
822 
823 DEFUN (history_timestamp_format_string, args, nargout,
824  "-*- texinfo -*-\n\
825 @deftypefn {Built-in Function} {@var{val} =} history_timestamp_format_string ()\n\
826 @deftypefnx {Built-in Function} {@var{old_val} =} history_timestamp_format_string (@var{new_val})\n\
827 @deftypefnx {Built-in Function} {} history_timestamp_format_string (@var{new_val}, \"local\")\n\
828 Query or set the internal variable that specifies the format string\n\
829 for the comment line that is written to the history file when Octave\n\
830 exits. The format string is passed to @code{strftime}. The default\n\
831 value is\n\
832 \n\
833 @example\n\
834 \"# Octave VERSION, %a %b %d %H:%M:%S %Y %Z <USER@@HOST>\"\n\
835 @end example\n\
836 \n\
837 When called from inside a function with the @qcode{\"local\"} option, the\n\
838 variable is changed locally for the function and any subroutines it calls. \n\
839 The original variable value is restored when exiting the function.\n\
840 @seealso{strftime, history_file, history_size, history_save}\n\
841 @end deftypefn")
842 {
843  return SET_INTERNAL_VARIABLE (history_timestamp_format_string);
844 }
845 
846 DEFUN (history_save, args, nargout,
847  "-*- texinfo -*-\n\
848 @deftypefn {Built-in Function} {@var{val} =} history_save ()\n\
849 @deftypefnx {Built-in Function} {@var{old_val} =} history_save (@var{new_val})\n\
850 @deftypefnx {Built-in Function} {} history_save (@var{new_val}, \"local\")\n\
851 Query or set the internal variable that controls whether commands entered\n\
852 on the command line are saved in the history file.\n\
853 \n\
854 When called from inside a function with the @qcode{\"local\"} option, the\n\
855 variable is changed locally for the function and any subroutines it calls. \n\
856 The original variable value is restored when exiting the function.\n\
857 @seealso{history_control, history_file, history_size, history_timestamp_format_string}\n\
858 @end deftypefn")
859 {
860  octave_value retval;
861 
862  bool old_history_save = ! command_history::ignoring_entries ();
863 
864  bool tmp = old_history_save;
865 
866  retval = set_internal_variable (tmp, args, nargout, "history_save");
867 
868  if (tmp != old_history_save)
870 
871  return retval;
872 }