Dynamixel  2.9.5
RoadNarrows Robotics Dynamixel Package
dynashell_readline.h
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: Dynamixel
4 //
5 // Program: dynashell
6 //
7 // File: dynashell_readline.h
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2015-01-12 10:56:06 -0700 (Mon, 12 Jan 2015) $
12  * $Rev: 3845 $
13  *
14  * \brief The Dynamixel Shell ReadLine Class.
15  *
16  * \note Define HAVE_READLINE to enable interface with libreadline.
17  *
18  * \author Robin Knight (robin.knight@roadnarrows.com)
19  *
20  * \copyright
21  * \h_copy 2011-2017. RoadNarrows LLC.\n
22  * http://www.roadnarrows.com\n
23  * All Rights Reserved
24  */
25 /*
26  * @EulaBegin@
27  *
28  * Unless otherwise stated explicitly, all materials contained are copyrighted
29  * and may not be used without RoadNarrows LLC's written consent,
30  * except as provided in these terms and conditions or in the copyright
31  * notice (documents and software) or other proprietary notice provided with
32  * the relevant materials.
33  *
34  * IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY
35  * MEMBERS/EMPLOYEES/CONTRACTORS OF ROADNARROWS OR DISTRIBUTORS OF THIS SOFTWARE
36  * BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
37  * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
38  * DOCUMENTATION, EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN
39  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * THE AUTHORS AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
42  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
43  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
44  * "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
45  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
46  *
47  * @EulaEnd@
48  */
49 ////////////////////////////////////////////////////////////////////////////////
50 
51 #ifndef _DYNASHELL_READLINE_H
52 #define _DYNASHELL_READLINE_H
53 
54 #include <sys/types.h>
55 #include <unistd.h>
56 #include <errno.h>
57 #include <string.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <time.h>
61 
62 #include <iostream>
63 #include <string>
64 #include <vector>
65 
66 #ifdef HAVE_READLINE
67 #include <readline/readline.h>
68 #include <readline/history.h>
69 #endif // HAVE_READLINE
70 
71 #include "dynashell_regex.h"
72 
73 using namespace std;
74 
75 
76 // ----------------------------------------------------------------------------
77 // Types
78 // ----------------------------------------------------------------------------
79 
80 /*!
81  * \brief Application-specific tab completion generator function type.
82  *
83  * \param nUid Registered unique id.
84  * \param sText Partial text string to complete.
85  * \param uTextLen Length of text.
86  * \param nState Generator state. If FIRST,then initialize any statics.
87  * \param sContext Generator context (i.e. canonical path).
88  * \param pAppArg Generator function optional application argument.
89  *
90  * \return If a first/next match is made, return allocated completed match.\n
91  * Otherwise return NULL.
92  */
93 typedef char *(*ReadLineAppGenFunc_T)(int nUid,
94  const char *sText,
95  size_t uTextLen,
96  int nState,
97  const char *sContext,
98  void *pAppArg);
99 
100 
101 // ----------------------------------------------------------------------------
102 // Class ReadLineEntry
103 // ----------------------------------------------------------------------------
104 
106 {
107 public:
108  ReadLineEntry();
109 
110  ReadLineEntry(const string &strRegEx,
111  ReadLineAppGenFunc_T fnAppGen,
112  void *pAppArg);
113 
114  ReadLineEntry(const char *sRegEx,
115  ReadLineAppGenFunc_T fnAppGen,
116  void *pAppArg);
117 
118  ReadLineEntry(const ReadLineEntry &src);
119 
120  ~ReadLineEntry();
121 
122  /*!
123  * \brief Check if entry is valid.
124  *
125  * \return Returns true or false.
126  */
127  bool IsValid()
128  {
129  return m_regex.IsValid();
130  }
131 
132  /*!
133  * \brief Get the unique id associated with this entry.
134  *
135  * \return Unique id.
136  */
137  int GetUid()
138  {
139  return m_nUid;
140  }
141 
142 protected:
143  int m_nUid; ///< unique id
144  RegEx m_regex; ///< applicatin matching regular expression
145  ReadLineAppGenFunc_T m_fnAppGen; ///< application-specific generator
146  void *m_pAppArg; ///< application-specific argument
147 
148  friend class ReadLine;
149 };
150 
151 
152 // ----------------------------------------------------------------------------
153 // Class ReadLine
154 // ----------------------------------------------------------------------------
155 
156 /*!
157  * \brief ReadLine class provides a c++ wrapper around the readline c library.
158  *
159  * \par Features:
160  * \li line input
161  * \li tab completion
162  * \li history
163  *
164  * If libreadline is not available, then only line input is available.
165  */
166 class ReadLine
167 {
168 public:
169 
170  static const int FIRST = 0; ///< first state
171  static const int NOT_REG = -1; ///< not registered return value
172  static ReadLine *ReadLineThis; ///< static pointer this single instance
173 
174  ReadLine(const string &strName);
175 
176  ReadLine(const char *sName);
177 
178  virtual ~ReadLine();
179 
180  /*!
181  * \brief Register application-specific tab-completion generator associated.
182  *
183  * \param strRegEx Regular expression applied to current readline buffer
184  * state.
185  * \param fnAppGen Application-specific generator function.
186  * \param pAppArg Optional application argument generator function.
187  *
188  * \return
189  * On successful registration, a unique id \h_ge 0 is returned.\n
190  * On regular expression evalution failure, the generator is not registered
191  * and ReadLine::NOT_REG is returned.
192  */
193  int RegisterGenerator(const string strRegEx,
194  ReadLineAppGenFunc_T fnAppGen,
195  void *pAppArg)
196  {
197  return RegisterGenerator(strRegEx.c_str(), fnAppGen, pAppArg);
198  }
199 
200  int RegisterGenerator(const char *sRegEx,
201  ReadLineAppGenFunc_T fnAppGen,
202  void *pAppArg);
203 
204  void UnregisterGenerator(int nUid);
205 
206  /*!
207  * \brief Interactively read a line of input from standard input.
208  *
209  * If the readline library feature is enabled, then the input is controlled
210  * by the readline() call along with history and tab completion.
211  *
212  * \param sPrompt Optional user prompt string.
213  *
214  * \return If no errors occurred and EOF is not encountered, an allocated,
215  * null-terminated line buffer is return. Else NULL is return.
216  */
217  char *iReadLine(const char *sPrompt)
218  {
219 #ifdef HAVE_READLINE
220  return readline(sPrompt); // fixed at stdin
221 #else
222  retrun fReadLine(stdin, sPrompt); // so then so are we
223 #endif // HAVE_READLINE
224  }
225 
226  static char *fReadLine(FILE *fp, const char *sPrompt);
227 
228  void AddToHistory(const char *sInput);
229 
230 
231  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
232  // Built-In Tab Completion Generators
233  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
234 
235  /*!
236  * \brief File name tab completion generator.
237  *
238  * \param sText Partial text string to complete.
239  * \param nState Generator state. If FIRST,then initialize any statics.
240  *
241  * \return
242  * If a first/next match is made, return allocated completed match.\n
243  * Otherwise return NULL.
244  */
245  static char *FileCompletionGenerator(const char *sText, int nState)
246  {
247 #ifdef HAVE_READLINE
248  return rl_filename_completion_function(sText, nState);
249 #else
250  return NULL;
251 #endif // HAVE_READLINE
252  }
253 
254  /*!
255  * \brief User name tab completion generator.
256  *
257  * \param sText Partial text string to complete.
258  * \param nState Generator state. If FIRST,then initialize any statics.
259  *
260  * \return
261  * If a first/next match is made, return allocated completed match.\n
262  * Otherwise return NULL.
263  */
264  static char *UserCompletionGenerator(const char *sText, int nState)
265  {
266 #ifdef HAVE_READLINE
267  return rl_username_completion_function(sText, nState);
268 #else
269  return NULL;
270 #endif // HAVE_READLINE
271  }
272 
273 
274  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
275  // Utilities
276  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
277 
278  /*!
279  * \brief Duplicate string.
280  *
281  * \param str String to dup.
282  *
283  * \return Duplicated, allocated char *.
284  */
285  static char *dupstr(const string &str)
286  {
287  return ReadLine::dupstr(str.c_str());
288  }
289 
290  static char *dupstr(const char *s);
291 
292  static string strip(string &str);
293 
294  static char *strip(char *s);
295 
296  /*!
297  * \brief Canonicalization of a string.
298  *
299  * \param s Null-terminated string to canonicalize.
300  * \param uLen (Sub)length of string to canonicalize.
301  *
302  * \return Return string holding canonical form.
303  */
304  static string c14n(const string &str, size_t nLen)
305  {
306  return ReadLine::c14n(str.c_str(), nLen);
307  }
308 
309  static string c14n(const char *s, size_t nLen);
310 
311  static int tokenize(char *s, char *tokv[], size_t tokmax);
312 
313  /*!
314  * \brief Count the words in the string.
315  *
316  * \param str String to count.
317  *
318  * \return Number of words.
319  */
320  static int wc(const string &str)
321  {
322  return ReadLine::wc(str.c_str());
323  }
324 
325  static int wc(const char *s);
326 
327 protected:
328  /*!
329  * \brief Internal registered generator map type.
330  */
331  typedef vector<ReadLineEntry> VecAppEntry;
332 
333  char *m_sName; ///< readline name
334  int m_nUidCounter; ///< unique id counter
335  VecAppEntry m_vecGenerators; ///< map of generators
336  VecAppEntry::iterator m_posMatched; ///< matched entry position
337  string m_strContext; ///< current readline buffer context
338  size_t m_uTextLen; ///< text length of text to generator
339 
340  static char **CompletionWrap(const char *sText, int nStart, int nEnd);
341 
342  char **Completion(const char *sText, int nStart, int nEnd);
343 
344  static char *GeneratorWrap(const char *sText, int nState);
345 
346  void MatchGenerator(int nEnd);
347 };
348 
349 
350 #endif // _DYNASHELL_READLINE_H
int RegisterGenerator(const string strRegEx, ReadLineAppGenFunc_T fnAppGen, void *pAppArg)
Register application-specific tab-completion generator associated.
RegEx m_regex
applicatin matching regular expression
int m_nUid
unique id
int GetUid()
Get the unique id associated with this entry.
VecAppEntry::iterator m_posMatched
matched entry position
static string c14n(const string &str, size_t nLen)
Canonicalization of a string.
ReadLineAppGenFunc_T m_fnAppGen
application-specific generator
VecAppEntry m_vecGenerators
map of generators
static char * dupstr(const string &str)
Duplicate string.
Regular Express Class.
static ReadLine * ReadLineThis
static pointer this single instance
char *(* ReadLineAppGenFunc_T)(int nUid, const char *sText, size_t uTextLen, int nState, const char *sContext, void *pAppArg)
Application-specific tab completion generator function type.
static int wc(const string &str)
Count the words in the string.
size_t m_uTextLen
text length of text to generator
int m_nUidCounter
unique id counter
ReadLine class provides a c++ wrapper around the readline c library.
char * m_sName
readline name
void * m_pAppArg
application-specific argument
bool IsValid()
Check if entry is valid.
char * iReadLine(const char *sPrompt)
Interactively read a line of input from standard input.
vector< ReadLineEntry > VecAppEntry
Internal registered generator map type.
The Dynamixel Shell Regular Expression Class.
string m_strContext
current readline buffer context
static char * FileCompletionGenerator(const char *sText, int nState)
File name tab completion generator.
static char * UserCompletionGenerator(const char *sText, int nState)
User name tab completion generator.