Statistics
| Branch: | Tag: | Revision:

amiro-os / core / src / aos_shell.c @ 3da12676

History | View | Annotate | Download (73.6 KB)

1
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2020  Thomas Schöpping et al.
4

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14

15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18

    
19
/**
20
 * @file    aos_shell.c
21
 * @brief   Shell code.
22
 * @details Shell code as well as shell related channels and streams.
23
 *
24
 * @addtogroup aos_shell
25
 * @{
26
 */
27

    
28
#include <amiroos.h>
29
#include <string.h>
30

    
31
#if (AMIROOS_CFG_SHELL_ENABLE == true) || defined(__DOXYGEN__)
32

    
33
/******************************************************************************/
34
/* LOCAL DEFINITIONS                                                          */
35
/******************************************************************************/
36

    
37
/**
38
 * @brief   Size of the escape sequence buffer.
39
 */
40
#if !defined(AOS_SHELL_ESCSEQUENCE_LENGTH) || defined(__DOXYGEN__)
41
#define AOS_SHELL_ESCSEQUENCE_LENGTH            8
42
#endif
43

    
44
/**
45
 * @brief   The character the input buffer is initialized with.
46
 */
47
#define INBUF_INIT_CHAR                         '\x07'
48

    
49
/**
50
 * @brief   Event mask to be set on OS related events.
51
 */
52
#define EVENTMASK_OS                            EVENT_MASK(0)
53

    
54
/**
55
 * @brief   Event mask to be set on a input event.
56
 */
57
#define EVENTMASK_INPUT                         EVENT_MASK(1)
58

    
59
/**
60
 * @brief   String that defines the INSERT key as specified by VT100.
61
 */
62
#define KEYSTRING_INSERT                        "\x1B\x5B\x32\x7E"
63

    
64
/**
65
 * @brief   String that defines the DEL key as specified by VT100.
66
 */
67
#define KEYSTRING_DELETE                        "\x1B\x5B\x33\x7E"
68

    
69
/**
70
 * @brief   String that defines the HOME key as specified by VT100.
71
 */
72
#define KEYSTRING_HOME                          "\x1B\x5B\x48"
73

    
74
/**
75
 * @brief   String that defines the END key as specified by VT100.
76
 */
77
#define KEYSTRING_END                           "\x1B\x5B\x46"
78

    
79
/**
80
 * @brief   String that defines the PGUP key as specified by VT100.
81
 */
82
#define KEYSTRING_PAGEUP                        "\x1B\x5B\x35\x7E"
83

    
84
/**
85
 * @brief   String that defines the PGUP key as specified by VT100.
86
 */
87
#define KEYSTRING_PAGEDOWN                      "\x1B\x5B\x36\x7E"
88

    
89
/**
90
 * @brief   String that defines the 'arrow down' key as specified by VT100.
91
 */
92
#define KEYSTRING_ARROWUP                       "\x1B\x5B\x41"
93

    
94
/**
95
 * @brief   String that defines the 'arrow up' key as specified by VT100.
96
 */
97
#define KEYSTRING_ARROWDOWN                     "\x1B\x5B\x42"
98

    
99
/**
100
 * @brief   String that defines the 'arrow left' key as specified by VT100.
101
 */
102
#define KEYSTRING_ARROWLEFT                     "\x1B\x5B\x44"
103

    
104
/**
105
 * @brief   String that defines the 'arrow right' key as specified by VT100.
106
 */
107
#define KEYSTRING_ARROWRIGHT                    "\x1B\x5B\x43"
108

    
109
/**
110
 * @brief   String that defines the CRTL + 'arrow up' key combination as specified by VT100.
111
 */
112
#define KEYSTRING_CTRL_ARROWUP                  "\x1B\x5B\x31\x3B\x35\x41"
113

    
114
/**
115
 * @brief   String that defines the CRTL + 'arrow down' key combination as specified by VT100.
116
 */
117
#define KEYSTRING_CTRL_ARROWDOWN                "\x1B\x5B\x31\x3B\x35\x42"
118

    
119
/**
120
 * @brief   String that defines the CRTL + 'arrow left' key combination as specified by VT100.
121
 */
122
#define KEYSTRING_CTRL_ARROWLEFT                "\x1B\x5B\x31\x3B\x35\x44"
123

    
124
/**
125
 * @brief   String that defines the CRTL + 'arrow right' key combination as specified by VT100.
126
 */
127
#define KEYSTRING_CTRL_ARROWRIGHT               "\x1B\x5B\x31\x3B\x35\x43"
128

    
129
/******************************************************************************/
130
/* EXPORTED VARIABLES                                                         */
131
/******************************************************************************/
132

    
133
/******************************************************************************/
134
/* LOCAL TYPES                                                                */
135
/******************************************************************************/
136

    
137
/*
138
 * forward declarations
139
 */
140
static size_t _channelwrite(void *instance, const uint8_t *bp, size_t n);
141
static size_t _channelread(void *instance, uint8_t *bp, size_t n);
142
static msg_t _channelput(void *instance, uint8_t b);
143
static msg_t _channelget(void *instance);
144
static msg_t _channelputt(void *instance, uint8_t b, sysinterval_t time);
145
static msg_t _channelgett(void *instance, sysinterval_t time);
146
static size_t _channelwritet(void *instance, const uint8_t *bp, size_t n, sysinterval_t time);
147
static size_t _channelreadt(void *instance, uint8_t *bp, size_t n, sysinterval_t time);
148
static msg_t _channelctl(void *instance, unsigned int operation, void *arg);
149
static size_t _streamwrite(void *instance, const uint8_t *bp, size_t n);
150
static size_t _stremread(void *instance, uint8_t *bp, size_t n);
151
static msg_t _streamput(void *instance, uint8_t b);
152
static msg_t _streamget(void *instance);
153

    
154
static const struct AosShellChannelVMT _channelvmt = {
155
  (size_t) 0,
156
  _channelwrite,
157
  _channelread,
158
  _channelput,
159
  _channelget,
160
  _channelputt,
161
  _channelgett,
162
  _channelwritet,
163
  _channelreadt,
164
  _channelctl,
165
};
166

    
167
static const struct AosShellStreamVMT _streamvmt = {
168
  (size_t) 0,
169
  _streamwrite,
170
  _stremread,
171
  _streamput,
172
  _streamget,
173
};
174

    
175
/**
176
 * @brief   Enumerator of special keyboard keys.
177
 */
178
typedef enum special_key {
179
  KEY_UNKNOWN,          /**< any/unknow key */
180
  KEY_AMBIGUOUS,        /**< key is ambiguous */
181
  KEY_TAB,              /**< tabulator key */
182
  KEY_BACKSPACE,        /**< backspace key */
183
  KEY_INSERT,           /**< insert key */
184
  KEY_DELETE,           /**< delete key */
185
  KEY_ESCAPE,           /**< escape key */
186
  KEY_HOME,             /**< home key */
187
  KEY_END,              /**< end key */
188
  KEY_PAGEUP,           /**< page up key */
189
  KEY_PAGEDOWN,         /**< page down key */
190
  KEY_ARROWUP,          /**< arrow up key */
191
  KEY_ARROWDOWN,        /**< arrow down key */
192
  KEY_ARROWLEFT,        /**< arrow left key */
193
  KEY_ARROWRIGHT,       /**< arrow right key */
194
  KEY_CTRL_ARROWUP,     /**< CTRL + arrow up key */
195
  KEY_CTRL_ARROWDOWN,   /**< CTRL + arrow down key */
196
  KEY_CTRL_ARROWLEFT,   /**< CTRL + arrow left key */
197
  KEY_CTRL_ARROWRIGHT,  /**< CTRL + arrow right key */
198
  KEY_CTRL_C,           /**< CTRL + C key */
199
} special_key_t;
200

    
201
/**
202
 * @brief   Enumerator for case (in)sensitive character matching.
203
 */
204
typedef enum charmatch {
205
  CHAR_MATCH_NOT    = 0,  /**< Characters do not match at all. */
206
  CHAR_MATCH_NCASE  = 1,  /**< Characters would match case insensitive. */
207
  CHAR_MATCH_CASE   = 2,  /**< Characters do match with case. */
208
} charmatch_t;
209

    
210
/**
211
 * @brief   Enumerator to encode shell actions.
212
 */
213
typedef enum aos_shellaction {
214
  ACTION_NONE,                  /**< No action at all. */
215
  ACTION_READCHAR,              /**< Read a printable character. */
216
  ACTION_AUTOCOMPLETE,          /**< Automatically comlete input by using available command. */
217
  ACTION_SUGGEST,               /**< Suggest matching available commands. */
218
  ACTION_EXECUTE,               /**< Execute input. */
219
  ACTION_DELETEBACKWARD,        /**< Delete a single character backwards. */
220
  ACTION_DELETEFORWARD,         /**< Delete a single character forwards. */
221
  ACTION_CLEAR,                 /**< Clear the input. */
222
  ACTION_RECALLPREVIOUS,        /**< Recall the previous (older) entry in the history. */
223
  ACTION_RECALLNEXT,            /**< Recall the next (more recent) entry in the history. */
224
  ACTION_RECALLOLDEST,          /**< Recall the oldest entry in the history. */
225
  ACTION_RECALLCURRENT,         /**< Recall the current input. */
226
  ACTION_CURSORLEFT,            /**< Move cursor one character to the left. */
227
  ACTION_CURSORRIGHT,           /**< Move cursor one character to the right. */
228
  ACTION_CURSORWORDLEFT,        /**< Move cursor one word to the left. */
229
  ACTION_CURSORWORDRIGHT,       /**< Move cursor one word to the right. */
230
  ACTION_CURSOR2END,            /**< Move cursor to the very right. */
231
  ACTION_CURSOR2START,          /**< Move cursor to the very left. */
232
  ACTION_RESET,                 /**< Reset the current input. */
233
  ACTION_INSERTTOGGLE,          /**< Toggle insertion mode. */
234
  ACTION_ESCSTART,              /**< Start an escape sequence (special keys). */
235
  ACTION_PRINTUNKNOWNSEQUENCE,  /**< Print an unknown escape sequence. */
236
} action_t;
237

    
238
/**
239
 * @brief   Struct that holds most important runtime data for the shell.
240
 * @details The structure is to be used by the shell thread main function as some kind of structured stack, which can be easily passed to other functions.
241
 */
242
typedef struct runtimedata {
243
  /**
244
   * @brief   Data related to the current input.
245
   */
246
  struct {
247
    /**
248
     * @brief   Length of the input.
249
     */
250
    size_t length;
251

    
252
    /**
253
     * @brief   Current position of the cursor in the input line.
254
     */
255
    size_t cursorpos;
256

    
257
    /**
258
     * @brief   Buffer to store escape sequences, which describe special characters.
259
     */
260
    char escseq[AOS_SHELL_ESCSEQUENCE_LENGTH];
261
  } input;
262

    
263
  /**
264
   * @brief   Data related to the entry or history buffer.
265
   */
266
  struct {
267
    /**
268
     * @brief   Current entry to be filled and executed.
269
     */
270
    size_t current;
271

    
272
    /**
273
     * @brief   Selected entry in the 'history' as preview.
274
     * @details A value of 0 indicates, that the line is cleared as a preview.
275
     *          A value of 1 indicates, that the current entry is selected.
276
     *          A value of t>1 indicates, that the entry t-1 in the past is selected.
277
     *          The value must never be greater than the number of entries available, of course.
278
     */
279
    size_t selected;
280

    
281
    /**
282
     * @brief   Selected entry in the 'history' that has been edited by the user.
283
     *          A value of 0 indicates, that there was no modification by the user yet (i.e. charcters, deletions or autofill).
284
     *          A value of 1 indicates, that the current entry was edited.
285
     *          A value of t>1 indicated, that a history entry was recalled and then edited.
286
     */
287
    size_t edited;
288
  } buffer;
289

    
290
  /**
291
   * @brief   The last action executed by the shell.
292
   */
293
  action_t lastaction;
294
} runtimedata_t;
295

    
296
/******************************************************************************/
297
/* LOCAL VARIABLES                                                            */
298
/******************************************************************************/
299

    
300
/******************************************************************************/
301
/* LOCAL FUNCTIONS                                                            */
302
/******************************************************************************/
303

    
304
/**
305
 * @brief   Implementation of the BaseAsynchronous write() method (inherited from BaseSequentialStream).
306
 */
307
static size_t _channelwrite(void *instance, const uint8_t *bp, size_t n)
308
{
309
  if (((AosShellChannel*)instance)->flags & AOS_SHELLCHANNEL_OUTPUT_ENABLED) {
310
    return streamWrite(((AosShellChannel*)instance)->asyncchannel, bp, n);
311
  } else {
312
    return 0;
313
  }
314
}
315

    
316
/**
317
 * @brief   Implementation of the BaseAsynchronous read() method (inherited from BaseSequentialStream).
318
 */
319
static size_t _channelread(void *instance, uint8_t *bp, size_t n)
320
{
321
  if (((AosShellChannel*)instance)->flags & AOS_SHELLCHANNEL_INPUT_ENABLED) {
322
    return streamRead(((AosShellChannel*)instance)->asyncchannel, bp, n);
323
  } else {
324
    return 0;
325
  }
326
}
327

    
328
/**
329
 * @brief   Implementation of the BaseAsynchronous put() method (inherited from BaseSequentialStream).
330
 */
331
static msg_t _channelput(void *instance, uint8_t b)
332
{
333
  if (((AosShellChannel*)instance)->flags & AOS_SHELLCHANNEL_OUTPUT_ENABLED) {
334
    return streamPut(((AosShellChannel*)instance)->asyncchannel, b);
335
  } else {
336
    return MSG_RESET;
337
  }
338
}
339

    
340
/**
341
 * @brief   Implementation of the BaseAsynchronous get() method (inherited from BaseSequentialStream).
342
 */
343
static msg_t _channelget(void *instance)
344
{
345
  if (((AosShellChannel*)instance)->flags & AOS_SHELLCHANNEL_INPUT_ENABLED) {
346