GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
oct-rl-hist.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2000-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include "oct-rl-hist.h"
31 
32 #if defined (USE_READLINE)
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include <readline/history.h>
39 
40 /* check_history_control, hc_erasedup, and the core of
41  octave_add_history were borrowed from Bash. */
42 
43 /* Check LINE against what HISTCONTROL says to do. Returns 1 if the line
44  should be saved; 0 if it should be discarded. */
45 static int
46 check_history_control (const char *line, int history_control)
47 {
48  HIST_ENTRY *temp;
49  int r;
50 
51  if (history_control == 0)
52  return 1;
53 
54  /* ignorespace or ignoreboth */
55  if ((history_control & HC_IGNSPACE) && *line == ' ')
56  return 0;
57 
58  /* ignoredups or ignoreboth */
59  if (history_control & HC_IGNDUPS)
60  {
61  using_history ();
62  temp = previous_history ();
63 
64  r = (temp == 0 || strcmp (temp->line, line));
65 
66  using_history ();
67 
68  if (r == 0)
69  return r;
70  }
71 
72  return 1;
73 }
74 
75 /* Remove all entries matching LINE from the history list. Triggered when
76  HISTCONTROL includes 'erasedups'. */
77 
78 static void
79 hc_erasedups (const char *line)
80 {
81  HIST_ENTRY *temp;
82  int r;
83 
84  using_history ();
85  while ((temp = previous_history ()))
86  {
87  if (! strcmp (temp->line, line))
88  {
89  r = where_history ();
90  remove_history (r);
91  }
92  }
93  using_history ();
94 }
95 
96 /* Check LINE against HISTCONTROL and add it to the history if it's OK.
97  Returns 1 if the line was saved in the history, 0 otherwise. */
98 
99 int
100 octave_add_history (const char *line, int history_control)
101 {
102  if (check_history_control (line, history_control))
103  {
104  /* We're committed to saving the line. If the user has requested it,
105  remove other matching lines from the history. */
106 
107  if (history_control & HC_ERASEDUPS)
108  hc_erasedups (line);
109 
110  add_history (line);
111 
112  return 1;
113  }
114 
115  return 0;
116 }
117 
118 int
120 {
121  return where_history ();
122 }
123 
124 int
126 {
127  return history_length;
128 }
129 
130 int
132 {
133  return max_input_history;
134 }
135 
136 int
137 octave_history_base (void)
138 {
139  return history_base;
140 }
141 
142 void
144 {
145  stifle_history (n);
146 }
147 
148 int
150 {
151  return unstifle_history ();
152 }
153 
154 int
156 {
157  return history_is_stifled ();
158 }
159 
160 int
162 {
163  return history_set_pos (n);
164 }
165 
166 int
167 octave_read_history (const char *f)
168 {
169  return read_history (f);
170 }
171 
172 void
174 {
175  using_history ();
176 }
177 
178 int
179 octave_read_history_range (const char *f, int b, int e)
180 {
181  return read_history_range (f, b, e);
182 }
183 
184 int
185 octave_write_history (const char *f)
186 {
187  return write_history (f);
188 }
189 
190 int
191 octave_append_history (int n, const char *f)
192 {
193  return append_history (n, f);
194 }
195 
196 int
197 octave_history_truncate_file (const char *f, int n)
198 {
199  return history_truncate_file (f, n);
200 }
201 
202 void
204 {
205  HIST_ENTRY *discard = remove_history (n);
206 
207  if (discard)
208  free (discard->line);
209 
210  free (discard);
211 }
212 
213 void
215 {
216  clear_history ();
217 }
218 
219 char *
221 {
222  HIST_ENTRY *h;
223 
224  char *retval = 0;
225 
226  if (history_set_pos (n))
227  {
228  h = current_history ();
229 
230  if (h)
231  retval = h->line;
232  }
233 
234  return retval;
235 }
236 
237 char *
238 octave_history_get (int n)
239 {
240  char *retval = 0;
241 
242  HIST_ENTRY *h = history_get (n);
243 
244  if (h)
245  retval = h->line;
246 
247  return retval;
248 }
249 
250 char **
251 octave_history_list (int limit, int number_lines)
252 {
253  static char **retval = 0;
254 
255  HIST_ENTRY **hlist = 0;
256 
257  if (retval)
258  {
259  char **p = retval;
260 
261  while (*p)
262  free (*p++);
263 
264  free (retval);
265 
266  retval = 0;
267  }
268 
269  hlist = history_list ();
270 
271  if (hlist)
272  {
273  int i, k;
274 
275  int beg = 0;
276  int end = 0;
277  while (hlist[end])
278  end++;
279 
280  beg = (limit < 0 || end < limit) ? 0 : (end - limit);
281 
282  retval = malloc ((size_t) (end - beg + 1) * sizeof (char *));
283  // FIXME: Should this call current_liboctave_error_handler instead?
284  if (! retval)
285  return retval;
286 
287  k = 0;
288  for (i = beg; i < end; i++)
289  {
290  char *line = hlist[i]->line;
291  size_t len = line ? strlen (line) : 0;
292  char *tmp = malloc (len + 64);
293 
294  if (tmp)
295  {
296  if (number_lines)
297  sprintf (tmp, "%5d %s", i + history_base,
298  line ? line : "");
299  else
300  strcpy (tmp, line ? line : "");
301 
302  retval[k++] = tmp;
303  }
304  }
305 
306  retval[k] = 0;
307  }
308 
309  return retval;
310 }
311 
312 void
313 octave_replace_history_entry (int which, const char *line)
314 {
315  HIST_ENTRY *discard = replace_history_entry (which, line, 0);
316 
317  if (discard)
318  free (discard->line);
319 
320  free (discard);
321 }
322 
323 #endif
line(const graphics_handle &mh, const graphics_handle &p)
Definition: graphics.h:7672
F77_RET_T const F77_DBLE const F77_DBLE * f
octave_idx_type n
Definition: mx-inlines.cc:761
T * r
Definition: mx-inlines.cc:781
void octave_stifle_history(int)
int octave_unstifle_history(void)
int octave_where_history(void)
void octave_clear_history(void)
char * octave_history_goto_mark(int n)
int octave_read_history_range(const char *, int, int)
int octave_write_history(const char *)
int octave_append_history(int, const char *)
int octave_read_history(const char *)
char ** octave_history_list(int, int)
int octave_max_input_history(void)
@ HC_IGNDUPS
Definition: oct-rl-hist.h:39
@ HC_ERASEDUPS
Definition: oct-rl-hist.h:40
@ HC_IGNSPACE
Definition: oct-rl-hist.h:38
int octave_history_length(void)
void octave_replace_history_entry(int, const char *)
char * octave_history_get(int n)
int octave_history_base(void)
int octave_history_set_pos(int)
int octave_add_history(const char *, int)
int octave_history_truncate_file(const char *, int)
void octave_using_history(void)
int octave_history_is_stifled(void)
void octave_remove_history(int)
T::size_type strlen(const typename T::value_type *str)
Definition: oct-string.cc:88
bool strcmp(const T &str_a, const T &str_b)
Octave string utility functions.
void * malloc(unsigned)
void free(void *)
F77_RET_T len
Definition: xerbla.cc:61