Revision cc33217b core/src/aos_shell.c

View differences:

core/src/aos_shell.c
94 94
 * @brief   Enumerator of special keyboard keys.
95 95
 */
96 96
typedef enum special_key {
97
  KEY_UNKNOWN,      /**< any/unknow key */
98
  KEY_AMBIGUOUS,    /**< key is ambiguous */
99
  KEY_TAB,          /**< tabulator key */
100
  KEY_ESCAPE,       /**< escape key */
101
  KEY_BACKSPACE,    /**< backspace key */
102
  KEY_INSERT,       /**< insert key */
103
  KEY_DELETE,       /**< delete key */
104
  KEY_HOME,         /**< home key */
105
  KEY_END,          /**< end key */
106
  KEY_PAGE_UP,      /**< page up key */
107
  KEY_PAGE_DOWN,    /**< page down key */
108
  KEY_ARROW_UP,     /**< arrow up key */
109
  KEY_ARROW_DOWN,   /**< arrow down key */
110
  KEY_ARROW_LEFT,   /**< arrow left key */
111
  KEY_ARROW_RIGHT,  /**< arrow right key */
97
  KEY_UNKNOWN,          /**< any/unknow key */
98
  KEY_AMBIGUOUS,        /**< key is ambiguous */
99
  KEY_TAB,              /**< tabulator key */
100
  KEY_ESCAPE,           /**< escape key */
101
  KEY_BACKSPACE,        /**< backspace key */
102
  KEY_INSERT,           /**< insert key */
103
  KEY_DELETE,           /**< delete key */
104
  KEY_HOME,             /**< home key */
105
  KEY_END,              /**< end key */
106
  KEY_PAGE_UP,          /**< page up key */
107
  KEY_PAGE_DOWN,        /**< page down key */
108
  KEY_ARROW_UP,         /**< arrow up key */
109
  KEY_ARROW_DOWN,       /**< arrow down key */
110
  KEY_ARROW_LEFT,       /**< arrow left key */
111
  KEY_ARROW_RIGHT,      /**< arrow right key */
112
  KEY_CTRL_ARROW_UP,    /**< CTRL + arrow up key */
113
  KEY_CTRL_ARROW_DOWN,  /**< CTRL + arrow down key */
114
  KEY_CTRL_ARROW_LEFT,  /**< CTRL + arrow left key */
115
  KEY_CTRL_ARROW_RIGHT, /**< CTRL + arrow right key */
112 116
} special_key_t;
113 117

  
114 118
/**
......
367 371
static special_key_t _interpreteEscapeSequence(const char seq[])
368 372
{
369 373
  // local variables
374
  char str[AOS_SHELL_ESCSEQUENCE_LENGTH];
375
  unsigned long strl = 0;
376
  const unsigned long seql = strlen(seq);
370 377
  bool ambiguous = false;
371
  int cmp = 0;
372 378

  
373 379
  // TAB
374 380
  /* not supported yet; use "\x09" instead */
......
377 383
  /* not supported yet; use "\x08" instead */
378 384

  
379 385
  // ESCAPE
380
  cmp = strcmp(seq, "\x1B");
381
  if (cmp == 0) {
386
  strncpy(str, "\x1B", AOS_SHELL_ESCSEQUENCE_LENGTH);
387
  strl = strlen(str);
388
  if (seql == strl && strncmp(seq, str, seql) == 0) {
382 389
    return KEY_ESCAPE;
383
  } else {
384
    ambiguous |= (cmp < 0);
390
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
391
    ambiguous = true;
385 392
  }
386 393

  
387 394
  // INSERT
388
  cmp = strcmp(seq, "\x1B\x5B\x32\x7E");
389
  if (cmp == 0) {
395
  strncpy(str, "\x1B\x5B\x32\x7E", AOS_SHELL_ESCSEQUENCE_LENGTH);
396
  strl = strlen(str);
397
  if (seql == strl && strncmp(seq, str, seql) == 0) {
390 398
    return KEY_INSERT;
391
  } else {
392
    ambiguous |= (cmp < 0);
399
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
400
    ambiguous = true;
393 401
  }
394 402

  
395 403
  // DELETE
396
  cmp = strcmp(seq, "\x1B\x5B\x33\x7E");
397
  if (cmp == 0) {
404
  strncpy(str, "\x1B\x5B\x33\x7E", AOS_SHELL_ESCSEQUENCE_LENGTH);
405
  strl = strlen(str);
406
  if (seql == strl && strncmp(seq, str, seql) == 0) {
398 407
    return KEY_DELETE;
399
  } else {
400
    ambiguous |= (cmp < 0);
408
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
409
    ambiguous = true;
401 410
  }
402 411

  
403 412
  // HOME
404
  cmp = strcmp(seq, "\x1B\x5B\x48");
405
  if (cmp == 0) {
413
  strncpy(str, "\x1B\x5B\x48", AOS_SHELL_ESCSEQUENCE_LENGTH);
414
  strl = strlen(str);
415
  if (seql == strl && strncmp(seq, str, seql) == 0) {
406 416
    return KEY_HOME;
407
  } else {
408
    ambiguous |= (cmp < 0);
417
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
418
    ambiguous = true;
409 419
  }
410 420

  
411 421
  // END
412
  cmp = strcmp(seq, "\x1B\x5B\x46");
413
  if (cmp == 0) {
422
  strncpy(str, "\x1B\x5B\x46", AOS_SHELL_ESCSEQUENCE_LENGTH);
423
  strl = strlen(str);
424
  if (seql == strl && strncmp(seq, str, seql) == 0) {
414 425
    return KEY_END;
415
  } else {
416
    ambiguous |= (cmp < 0);
426
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
427
    ambiguous = true;
417 428
  }
418 429

  
419 430
  // PAGE UP
420
  cmp = strcmp(seq, "\x1B\x5B\x35\x7E");
421
  if (cmp == 0) {
431
  strncpy(str, "\x1B\x5B\x35\x7E", AOS_SHELL_ESCSEQUENCE_LENGTH);
432
  strl = strlen(str);
433
  if (seql == strl && strncmp(seq, str, seql) == 0) {
422 434
    return KEY_PAGE_UP;
423
  } else {
424
    ambiguous |= (cmp < 0);
435
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
436
    ambiguous = true;
425 437
  }
426 438

  
427 439
  // PAGE DOWN
428
  cmp = strcmp(seq, "\x1B\x5B\x36\x7E");
429
  if (cmp == 0) {
440
  strncpy(str, "\x1B\x5B\x36\x7E", AOS_SHELL_ESCSEQUENCE_LENGTH);
441
  strl = strlen(str);
442
  if (seql == strl && strncmp(seq, str, seql) == 0) {
430 443
    return KEY_PAGE_DOWN;
431
  } else {
432
    ambiguous |= (cmp < 0);
444
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
445
    ambiguous = true;
433 446
  }
434 447

  
435 448
  // ARROW UP
436
  cmp = strcmp(seq, "\x1B\x5B\x41");
437
  if (cmp == 0) {
449
  strncpy(str, "\x1B\x5B\x41", AOS_SHELL_ESCSEQUENCE_LENGTH);
450
  strl = strlen(str);
451
  if (seql == strl && strncmp(seq, str, seql) == 0) {
438 452
    return KEY_ARROW_UP;
439
  } else {
440
    ambiguous |= (cmp < 0);
453
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
454
    ambiguous = true;
441 455
  }
442 456

  
443 457
  // ARROW DOWN
444
  cmp = strcmp(seq, "\x1B\x5B\x42");
445
  if (cmp == 0) {
458
  strncpy(str, "\x1B\x5B\x42", AOS_SHELL_ESCSEQUENCE_LENGTH);
459
  strl = strlen(str);
460
  if (seql == strl && strncmp(seq, str, seql) == 0) {
446 461
    return KEY_ARROW_DOWN;
447
  } else {
448
    ambiguous |= (cmp < 0);
462
  } else if (seql < strl && strncmp(seq, str, seql) == 0) {
463
    ambiguous = true;
449 464
  }
450 465

  
451 466
  // ARROW LEFT
452
  cmp = strcmp(seq, "\x1B\x5B\x44");
453
  if (cmp == 0) {
467
  strncpy(str, "\x1B\x5B\x44", AOS_SHELL_ESCSEQUENCE_LENGTH);
468
  strl = strlen(str);
469
  if (seql == strl && strncmp(seq, str, seql) == 0) {
454 470
    return KEY_ARROW_LEFT;
455
  } else {
456
    ambiguous |= (cmp < 0);
471
  } else if (seql < strl && strncmp(seq, str, seql) == 0) {
472
    ambiguous = true;
457 473
  }
458 474

  
459 475
  // ARROW RIGHT
460
  cmp = strcmp(seq, "\x1B\x5B\x43");
461
  if (cmp == 0) {
476
  strncpy(str, "\x1B\x5B\x43", AOS_SHELL_ESCSEQUENCE_LENGTH);
477
  strl = strlen(str);
478
  if (seql == strl && strncmp(seq, str, seql) == 0) {
462 479
    return KEY_ARROW_RIGHT;
463
  } else {
464
    ambiguous |= (cmp < 0);
480
  } else if (seql < strl && strncmp(seq, str, seql) == 0) {
481
    ambiguous = true;
482
  }
483

  
484
  // CTRL + ARROW UP
485
  strncpy(str, "\x1B\x5B\x31\x3B\x35\x41", AOS_SHELL_ESCSEQUENCE_LENGTH);
486
  strl = strlen(str);
487
  if (seql == strl && strncmp(seq, str, seql) == 0) {
488
    return KEY_CTRL_ARROW_UP;
489
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
490
    ambiguous = true;
491
  }
492

  
493
  // CTRL + ARROW DOWN
494
  strncpy(str, "\x1B\x5B\x31\x3B\x35\x42", AOS_SHELL_ESCSEQUENCE_LENGTH);
495
  strl = strlen(str);
496
  if (seql == strl && strncmp(seq, str, seql) == 0) {
497
    return KEY_CTRL_ARROW_DOWN;
498
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
499
    ambiguous = true;
500
  }
501

  
502
  // CTRL + ARROW LEFT
503
  strncpy(str, "\x1B\x5B\x31\x3B\x35\x44", AOS_SHELL_ESCSEQUENCE_LENGTH);
504
  strl = strlen(str);
505
  if (seql == strl && strncmp(seq, str, seql) == 0) {
506
    return KEY_CTRL_ARROW_LEFT;
507
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
508
    ambiguous = true;
509
  }
510

  
511
  // CTRL + ARROW RIGHT
512
  strncpy(str, "\x1B\x5B\x31\x3B\x35\x43", AOS_SHELL_ESCSEQUENCE_LENGTH);
513
  strl = strlen(str);
514
  if (seql == strl && strncmp(seq, str, seql) == 0) {
515
    return KEY_CTRL_ARROW_RIGHT;
516
  } else if(seql < strl && strncmp(seq, str, seql) == 0) {
517
    ambiguous = true;
465 518
  }
466 519

  
467 520
  return ambiguous ? KEY_AMBIGUOUS : KEY_UNKNOWN;
......
491 544

  
492 545
  // move cursor right by printing line content
493 546
  while (pos < to) {
494
    streamPut(&shell->stream, shell->line[pos]);
547
    streamPut(&shell->stream, shell->input.line[pos]);
495 548
    ++pos;
496 549
  }
497 550

  
......
515 568
  size_t cnt;
516 569

  
517 570
  for (cnt = 0; from + cnt < to; ++cnt) {
518
    streamPut(&shell->stream, shell->line[from + cnt]);
571
    streamPut(&shell->stream, shell->input.line[from + cnt]);
519 572
  }
520 573

  
521 574
  return cnt;
522 575
}
523 576

  
577
static int _readChar(aos_shell_t* shell, const char c) {
578
  aosDbgCheck(shell != NULL);
579

  
580
  // check whether input line is already full
581
  if (shell->inputdata.lineend + 1 >= shell->input.width) {
582
    return 0;
583
  } else {
584
    // clear old line content on first input
585
    if (shell->inputdata.noinput) {
586
      memset(shell->input.line, '\0', shell->input.width);
587
      shell->inputdata.noinput = false;
588
    }
589
    // overwrite content
590
    if (shell->config & AOS_SHELL_CONFIG_INPUT_OVERWRITE) {
591
      shell->input.line[shell->inputdata.cursorpos] = c;
592
      ++shell->inputdata.cursorpos;
593
      shell->inputdata.lineend = (shell->inputdata.cursorpos > shell->inputdata.lineend) ? shell->inputdata.cursorpos : shell->inputdata.lineend;
594
      streamPut(&shell->stream, (uint8_t)c);
595
    }
596
    // insert character
597
    else {
598
      memmove(&(shell->input.line[shell->inputdata.cursorpos+1]), &(shell->input.line[shell->inputdata.cursorpos]), shell->inputdata.lineend - shell->inputdata.cursorpos);
599
      shell->input.line[shell->inputdata.cursorpos] = c;
600
      ++shell->inputdata.lineend;
601
      _printLine(shell, shell->inputdata.cursorpos, shell->inputdata.lineend);
602
      ++shell->inputdata.cursorpos;
603
      _moveCursor(shell, shell->inputdata.lineend, shell->inputdata.cursorpos);
604
    }
605
    return 1;
606
  }
607
}
608

  
524 609
/**
525 610
 * @brief   Compare two characters.
526 611
 *
......
654 739
    key = KEY_UNKNOWN;
655 740

  
656 741
    // parse escape sequence
657
    if (shell->inputdata.escp > 0) {
658
      shell->inputdata.escseq[shell->inputdata.escp] = c;
659
      ++shell->inputdata.escp;
742
    if (strlen(shell->inputdata.escseq) > 0) {
743
      shell->inputdata.escseq[strlen(shell->inputdata.escseq)] = c;
660 744
      key = _interpreteEscapeSequence(shell->inputdata.escseq);
661
      if (key == KEY_AMBIGUOUS) {
662
        // read next byte to resolve ambiguity
663
        continue;
664
      } else {
665
        /*
666
         * If the escape sequence could either be parsed sucessfully
667
         * or there is no match (KEY_UNKNOWN),
668
         * reset the sequence variable and interprete key/character
669
         */
670
        shell->inputdata.escp = 0;
671
        memset(shell->inputdata.escseq, '\0', sizeof(shell->inputdata.escseq)*sizeof(shell->inputdata.escseq[0]));
745
      switch (key) {
746
        case KEY_AMBIGUOUS:
747
          // read next byte to resolve ambiguity
748
          continue;
749
        case KEY_UNKNOWN:
750
          // do nothing here, but handle the unknown sequence below
751
          break;
752
        default:
753
          // reset the sequence variable and buffer
754
          memset(shell->inputdata.escseq, '\0', sizeof(shell->inputdata.escseq)*sizeof(shell->inputdata.escseq[0]));
755
          break;
672 756
      }
673 757
    }
674 758

  
......
678 762
      action = AOS_SHELL_ACTION_NONE;
679 763

  
680 764
      // printable character
681
      if (key == KEY_UNKNOWN && c >= '\x20' && c <= '\x7E') {
765
      if (key == KEY_UNKNOWN && strlen(shell->inputdata.escseq) == 0 && c >= '\x20' && c <= '\x7E') {
682 766
        action = AOS_SHELL_ACTION_READCHAR;
683 767
      }
684 768

  
......
716 800
        }
717 801
      }
718 802

  
719
      // 'page up' of 'arrow up' key
720
      else if (key == KEY_PAGE_UP || key == KEY_ARROW_UP) {
803
      // 'page up' key or CTRL + 'arrow up' key combination
804
      else if (key == KEY_PAGE_UP || key == KEY_CTRL_ARROW_UP) {
721 805
        // ignore if there was some input
722 806
        if (shell->inputdata.noinput) {
723 807
          action = AOS_SHELL_ACTION_RECALLLAST;
724 808
        }
725 809
      }
726 810

  
727
      // 'page down' key, 'arrow done' key, 'end of test' character or 'end of transmission' character
728
      else if (key == KEY_PAGE_DOWN || key == KEY_ARROW_DOWN || c == '\x03' || c == '\x03') {
811
      // 'page down' key, 'arrow down' key, 'end of test' character or 'end of transmission' character, or CTRL + 'arrow down' key combination
812
      else if (key == KEY_PAGE_DOWN || key == KEY_ARROW_DOWN || c == '\x03' || c == '\x03' || key == KEY_CTRL_ARROW_DOWN) {
729 813
        // ignore if line is empty
730 814
        if (shell->inputdata.lineend > 0) {
731 815
          action = AOS_SHELL_ACTION_CLEAR;
......
758 842

  
759 843
      // 'arrow right' key
760 844
      else if (key == KEY_ARROW_RIGHT) {
761
        // irgnore if cursor is very right
845
        // ignore if cursor is very right
762 846
        if (shell->inputdata.cursorpos < shell->inputdata.lineend) {
763 847
          action = AOS_SHELL_ACTION_CURSORRIGHT;
764 848
        }
765 849
      }
766 850

  
851
      // CTRL + 'arrow left' key combination
852
      else if (key == KEY_CTRL_ARROW_LEFT) {
853
        // ignore if cursor is very left
854
        if (shell->inputdata.cursorpos > 0) {
855
          action = AOS_SHELL_ACTION_CURSORWORDLEFT;
856
        }
857
      }
858

  
859
      // CTRL + 'arrow right' key combination
860
      else if (key == KEY_CTRL_ARROW_RIGHT) {
861
        // ignore if cursor is very right
862
        if (shell->inputdata.cursorpos < shell->inputdata.lineend) {
863
          action = AOS_SHELL_ACTION_CURSORWORDRIGHT;
864
        }
865
      }
866

  
767 867
      // carriage return ('\r') or line feed ('\n') character
768 868
      else if (c == '\x0D' || c == '\x0A') {
769 869
        action = AOS_SHELL_ACTION_EXECUTE;
......
773 873
      else if (key == KEY_ESCAPE || c == '\x1B') {
774 874
        action = AOS_SHELL_ACTION_ESCSTART;
775 875
      }
876

  
877
      // unknown escape sequence
878
      else if (key == KEY_UNKNOWN && strlen(shell->inputdata.escseq) > 0) {
879
        action = AOS_SHELL_ACTION_PRINTUNKNOWNSEQUENCE;
880
      }
776 881
    }
777 882

  
778 883
    /* handle function */
779 884
    switch (action) {
780 885
      case AOS_SHELL_ACTION_READCHAR:
781 886
      {
782
        // line is full
783
        if (shell->inputdata.lineend + 1 >= shell->linesize) {
887
        if (_readChar(shell, c) == 0) {
888
          // line is full
784 889
          _moveCursor(shell, shell->inputdata.cursorpos, shell->inputdata.lineend);
785 890
          chprintf((BaseSequentialStream*)&shell->stream, "\n\tmaximum line width reached\n");
786 891
          _printPrompt(shell);
787 892
          _printLine(shell, 0, shell->inputdata.lineend);
788 893
          _moveCursor(shell, shell->inputdata.lineend, shell->inputdata.cursorpos);
789 894
        }
790
        // read character
791
        else {
792
          // clear old line content on first input
793
          if (shell->inputdata.noinput) {
794
            memset(shell->line, '\0', shell->linesize);
795
            shell->inputdata.noinput = false;
796
          }
797
          // overwrite content
798
          if (shell->config & AOS_SHELL_CONFIG_INPUT_OVERWRITE) {
799
            shell->line[shell->inputdata.cursorpos] = c;
800
            ++shell->inputdata.cursorpos;
801
            shell->inputdata.lineend = (shell->inputdata.cursorpos > shell->inputdata.lineend) ? shell->inputdata.cursorpos : shell->inputdata.lineend;
802
            streamPut(&shell->stream, (uint8_t)c);
803
          }
804
          // insert character
805
          else {
806
            memmove(&(shell->line[shell->inputdata.cursorpos+1]), &(shell->line[shell->inputdata.cursorpos]), shell->inputdata.lineend - shell->inputdata.cursorpos);
807
            shell->line[shell->inputdata.cursorpos] = c;
808
            ++shell->inputdata.lineend;
809
            _printLine(shell, shell->inputdata.cursorpos, shell->inputdata.lineend);
810
            ++shell->inputdata.cursorpos;
811
            _moveCursor(shell, shell->inputdata.lineend, shell->inputdata.cursorpos);
812
          }
813
        }
814 895
        break;
815 896
      }
816 897

  
817 898
      case AOS_SHELL_ACTION_AUTOFILL:
818 899
      {
819
        const char* fill = shell->line;
900
        const char* fill = shell->input.line;
820 901
        size_t cmatch = shell->inputdata.cursorpos;
821 902
        charmatch_t matchlevel = CHAR_MATCH_NOT;
822 903
        size_t n;
......
837 918
            fill = cmd->name;
838 919
            // break the loop only if there are no case mismatches with the input
839 920
            n = shell->inputdata.cursorpos;
840
            _strccmp(fill, shell->line, false, &n, &mlvl);
921
            _strccmp(fill, shell->input.line, false, &n, &mlvl);
841 922
            if (mlvl == CHAR_MATCH_CASE) {
842 923
              break;
843 924
            }
......
845 926
          // if a not exact match was found
846 927
          else if (cmatch + cmp > shell->inputdata.cursorpos) {
847 928
            // if this is the first one
848
            if (fill == shell->line) {
929
            if (fill == shell->input.line) {
849 930
              cmatch += cmp;
850 931
              fill = cmd->name;
851 932
            }
......
859 940
        }
860 941
        // evaluate if there are case mismatches
861 942
        n = cmatch;
862
        _strccmp(shell->line, fill, shell->config & AOS_SHELL_CONFIG_MATCH_CASE, &n, &matchlevel);
943
        _strccmp(shell->input.line, fill, shell->config & AOS_SHELL_CONFIG_MATCH_CASE, &n, &matchlevel);
863 944
        // print the auto fill if any
864 945
        if (cmatch > shell->inputdata.cursorpos || (cmatch == shell->inputdata.cursorpos && matchlevel == CHAR_MATCH_NCASE)) {
865 946
          shell->inputdata.noinput = false;
866 947
          // limit auto fill so it will not overflow the line width
867
          if (shell->inputdata.lineend + (cmatch - shell->inputdata.cursorpos) > shell->linesize) {
868
            cmatch = shell->linesize - shell->inputdata.lineend + shell->inputdata.cursorpos;
948
          if (shell->inputdata.lineend + (cmatch - shell->inputdata.cursorpos) > shell->input.width) {
949
            cmatch = shell->input.width - shell->inputdata.lineend + shell->inputdata.cursorpos;
869 950
          }
870 951
          // move trailing memory further in the line
871
          memmove(&(shell->line[cmatch]), &(shell->line[shell->inputdata.cursorpos]), shell->inputdata.lineend - shell->inputdata.cursorpos);
952
          memmove(&(shell->input.line[cmatch]), &(shell->input.line[shell->inputdata.cursorpos]), shell->inputdata.lineend - shell->inputdata.cursorpos);
872 953
          shell->inputdata.lineend += cmatch - shell->inputdata.cursorpos;
873 954
          // if there was no incorrect case when matching
874 955
          if (matchlevel == CHAR_MATCH_CASE) {
875 956
            // insert fill command name to line
876
            memcpy(&(shell->line[shell->inputdata.cursorpos]), &(fill[shell->inputdata.cursorpos]), cmatch - shell->inputdata.cursorpos);
957
            memcpy(&(shell->input.line[shell->inputdata.cursorpos]), &(fill[shell->inputdata.cursorpos]), cmatch - shell->inputdata.cursorpos);
877 958
            // print the output
878 959
            _printLine(shell, shell->inputdata.cursorpos, shell->inputdata.lineend);
879 960
          } else {
880 961
            // overwrite line with fill command name
881
            memcpy(shell->line, fill, cmatch);
962
            memcpy(shell->input.line, fill, cmatch);
882 963
            // reprint the whole line
883 964
            _moveCursor(shell, shell->inputdata.cursorpos, 0);
884 965
            _printLine(shell, 0, shell->inputdata.lineend);
......
898 979
          // compare line content with command, excpet if cursorpos=0
899 980
          size_t i = shell->inputdata.cursorpos;
900 981
          if (shell->inputdata.cursorpos > 0) {
901
            _strccmp(shell->line, cmd->name, true, &i, NULL);
982
            _strccmp(shell->input.line, cmd->name, true, &i, NULL);
902 983
          }
903 984
          const int cmp = (i < shell->inputdata.cursorpos) ?
904 985
                            (i - shell->inputdata.cursorpos) :
......
940 1021
      case AOS_SHELL_ACTION_DELETEFORWARD:
941 1022
      {
942 1023
        --shell->inputdata.lineend;
943
        memmove(&(shell->line[shell->inputdata.cursorpos]), &(shell->line[shell->inputdata.cursorpos+1]), shell->inputdata.lineend - shell->inputdata.cursorpos);
1024
        memmove(&(shell->input.line[shell->inputdata.cursorpos]), &(shell->input.line[shell->inputdata.cursorpos+1]), shell->inputdata.lineend - shell->inputdata.cursorpos);
944 1025
        _printLine(shell, shell->inputdata.cursorpos, shell->inputdata.lineend);
945 1026
        streamPut(&shell->stream, ' ');
946 1027
        _moveCursor(shell, shell->inputdata.lineend + 1, shell->inputdata.cursorpos);
......
950 1031
      case AOS_SHELL_ACTION_DELETEBACKWARD:
951 1032
      {
952 1033
        --shell->inputdata.cursorpos;
953
        memmove(&(shell->line[shell->inputdata.cursorpos]), &(shell->line[shell->inputdata.cursorpos+1]), shell->inputdata.lineend - shell->inputdata.cursorpos);
1034
        memmove(&(shell->input.line[shell->inputdata.cursorpos]), &(shell->input.line[shell->inputdata.cursorpos+1]), shell->inputdata.lineend - shell->inputdata.cursorpos);
954 1035
        --shell->inputdata.lineend;
955
        shell->line[shell->inputdata.lineend] = '\0';
1036
        shell->input.line[shell->inputdata.lineend] = '\0';
956 1037
        _moveCursor(shell, shell->inputdata.cursorpos + 1, shell->inputdata.cursorpos);
957 1038
        _printLine(shell, shell->inputdata.cursorpos, shell->inputdata.lineend);
958 1039
        streamPut(&shell->stream, ' ');
......
967 1048
        size_t nul_start = 0;
968 1049
        size_t nul_end = 0;
969 1050
        // search line for a NUL byte
970
        while (nul_start < shell->linesize) {
971
          if (shell->line[nul_start] == '\0') {
1051
        while (nul_start < shell->input.width) {
1052
          if (shell->input.line[nul_start] == '\0') {
972 1053
            nul_end = nul_start + 1;
973 1054
            // keep searcjing for a byte that is not NUL
974
            while (nul_end < shell->linesize) {
975
              if (shell->line[nul_end] != '\0') {
1055
            while (nul_end < shell->input.width) {
1056
              if (shell->input.line[nul_end] != '\0') {
976 1057
                // an intermediate NUL sequence was found
977
                memset(&(shell->line[nul_start]), ' ', nul_end - nul_start);
1058
                memset(&(shell->input.line[nul_start]), ' ', nul_end - nul_start);
978 1059
                shell->inputdata.lineend = nul_end + 1;
979 1060
                break;
980 1061
              } else {
......
1035 1116
        break;
1036 1117
      }
1037 1118

  
1119
      case AOS_SHELL_ACTION_CURSORWORDLEFT:
1120
      {
1121
        size_t cpos = shell->inputdata.cursorpos;
1122
        while (cpos > 0 && shell->input.line[cpos-1] == ' ') {
1123
          --cpos;
1124
        }
1125
        while (cpos > 0 && shell->input.line[cpos-1] != ' ') {
1126
          --cpos;
1127
        }
1128
        _moveCursor(shell, shell->inputdata.cursorpos, cpos);
1129
        shell->inputdata.cursorpos = cpos;
1130
        break;
1131
      }
1132

  
1133
      case AOS_SHELL_ACTION_CURSORWORDRIGHT:
1134
      {
1135
        size_t cpos = shell->inputdata.cursorpos;
1136
        while (cpos < shell->inputdata.lineend && shell->input.line[cpos] != ' ') {
1137
          ++cpos;
1138
        }
1139
        while (cpos < shell->inputdata.lineend && shell->input.line[cpos] == ' ') {
1140
          ++cpos;
1141
        }
1142
        _moveCursor(shell, shell->inputdata.cursorpos, cpos);
1143
        shell->inputdata.cursorpos = cpos;
1144
        break;
1145
      }
1146

  
1038 1147
      case AOS_SHELL_ACTION_EXECUTE:
1039 1148
      {
1040 1149
        streamPut(&shell->stream, '\n');
1041 1150
        // set the number of read bytes and return
1042 1151
        if (!shell->inputdata.noinput) {
1043
          *n = shell->linesize - shell->inputdata.lineend;
1152
          *n = shell->input.width - shell->inputdata.lineend;
1044 1153
          // fill the remainder of the line with NUL bytes
1045
          memset(&(shell->line[shell->inputdata.lineend]), '\0', *n);
1154
          memset(&(shell->input.line[shell->inputdata.lineend]), '\0', *n);
1046 1155
          // reset static variables
1047 1156
          shell->inputdata.noinput = true;
1048 1157
        }
......
1052 1161
      case AOS_SHELL_ACTION_ESCSTART:
1053 1162
      {
1054 1163
        shell->inputdata.escseq[0] = c;
1055
        ++shell->inputdata.escp;
1164
        break;
1165
      }
1166

  
1167
      case AOS_SHELL_ACTION_PRINTUNKNOWNSEQUENCE:
1168
      {
1169
        size_t seqc = 1; // element 0 would be unprintible ESC character
1170
        while (shell->inputdata.escseq[seqc] != '\0') {
1171
          _readChar(shell, shell->inputdata.escseq[seqc]);
1172
          ++seqc;
1173
        }
1174
        memset(shell->inputdata.escseq, '\0', sizeof(shell->inputdata.escseq)*sizeof(shell->inputdata.escseq[0]));
1056 1175
        break;
1057 1176
      }
1058 1177

  
1059 1178
      case AOS_SHELL_ACTION_NONE:
1060
      default:
1061 1179
      {
1062 1180
        // do nothing (ignore input) and read next byte
1063 1181
        continue;
......
1097 1215
  size_t arg = 0;
1098 1216

  
1099 1217
  // iterate through the line
1100
  for (char* c = shell->line; c < shell->line + shell->linesize; ++c) {
1218
  for (char* c = shell->input.line; c < shell->input.line + shell->input.width; ++c) {
1101 1219
    // terminate at first NUL byte
1102 1220
    if (*c == '\0') {
1103 1221
      state = END;
......
1151 1269
 * @param[in] arglist       Pointer to the argument buffer.
1152 1270
 * @param[in] arglistsize   Size of te argument buffer.
1153 1271
 */
1154
void aosShellInit(aos_shell_t* shell, event_source_t* oseventsource,  const char* prompt, char* line, size_t linesize, char** arglist, size_t arglistsize)
1272
void aosShellInit(aos_shell_t* shell, event_source_t* oseventsource, const char* prompt, char* line, size_t linesize, char** arglist, size_t arglistsize)
1155 1273
{
1156 1274
  aosDbgCheck(shell != NULL);
1157 1275
  aosDbgCheck(oseventsource != NULL);
......
1167 1285
  shell->commands = NULL;
1168 1286
  shell->execstatus.command = NULL;
1169 1287
  shell->execstatus.retval = 0;
1170
  shell->line = line;
1171
  shell->linesize = linesize;
1288
  shell->input.line = line;
1289
  shell->input.width = linesize;
1172 1290
  shell->inputdata.lastaction = AOS_SHELL_ACTION_NONE;
1173
  shell->inputdata.escp = 0;
1174 1291
  memset(shell->inputdata.escseq, '\0', sizeof(shell->inputdata.escseq)*sizeof(shell->inputdata.escseq[0]));
1175 1292
  shell->inputdata.cursorpos = 0;
1176 1293
  shell->inputdata.lineend = 0;
......
1179 1296
  shell->arglistsize = arglistsize;
1180 1297
  shell->config = 0x00;
1181 1298

  
1182
  // initialize arrays
1183
  memset(shell->line, '\0', shell->linesize);
1299
  // initialize buffers
1300
  memset(shell->input.line, '\0', shell->input.width);
1184 1301
  for (size_t a = 0; a < shell->arglistsize; ++a) {
1185 1302
    shell->arglist[a] = NULL;
1186 1303
  }
......
1566 1683

  
1567 1684
              // if no matching command was found, print an error
1568 1685
              if (cmd == NULL) {
1569
                chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "%s: command not found\n", ((aos_shell_t*)shell)->arglist[0]);
1686
                chprintf((BaseSequentialStream*)&((aos_shell_t*)shell)->stream, "\tcommand '%s' not found\n", ((aos_shell_t*)shell)->arglist[0]);
1570 1687
              }
1571 1688
            }
1572 1689

  

Also available in: Unified diff