mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
bios: add auto completion for commands
This commit is contained in:
parent
fc2b8226c5
commit
74dc444b02
5 changed files with 216 additions and 0 deletions
|
@ -26,6 +26,12 @@ OBJECTS = isr.o \
|
|||
cmd_spi_flash.o \
|
||||
cmd_usddrphy.o
|
||||
|
||||
ifneq "$(or $(TERM_NO_COMPLETE),$(TERM_MINI))" ""
|
||||
CFLAGS += -DTERM_NO_COMPLETE
|
||||
else
|
||||
OBJECTS += complete.o
|
||||
endif
|
||||
|
||||
ifdef TERM_NO_HIST
|
||||
CFLAGS += -DTERM_NO_HIST
|
||||
endif
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#define MAX_PARAM 8
|
||||
|
||||
#define HIST_DEPTH 10 /* Used in string list, complete.c */
|
||||
|
||||
#define MISC_CMDS 0
|
||||
#define SYSTEM_CMDS 1
|
||||
#define CACHE_CMDS 2
|
||||
|
|
174
litex/soc/software/bios/complete.c
Normal file
174
litex/soc/software/bios/complete.c
Normal file
|
@ -0,0 +1,174 @@
|
|||
// This file is Copyright (c) 2020 Franck Jullien <franck.jullien@gmail.com>
|
||||
//
|
||||
// Largely inspired/copied from U-boot and Barebox projects wich are:
|
||||
// Sascha Hauer, Pengutronix, <s.hauer@pengutronix.de>
|
||||
|
||||
// License: BSD
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "readline.h"
|
||||
#include "helpers.h"
|
||||
#include "command.h"
|
||||
#include "complete.h"
|
||||
|
||||
static int tab_pressed = 0;
|
||||
|
||||
char sl[HIST_DEPTH][CMD_LINE_BUFFER_SIZE];
|
||||
int sl_idx = 0;
|
||||
|
||||
char out[CMD_LINE_BUFFER_SIZE];
|
||||
|
||||
static void string_list_init(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < HIST_DEPTH; i++)
|
||||
sl[i][0] = 0;
|
||||
}
|
||||
|
||||
static int string_list_add(const char *string)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < HIST_DEPTH; i++) {
|
||||
if (sl[i][0] == 0) {
|
||||
strncpy(&sl[i][0], string, CMD_LINE_BUFFER_SIZE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int string_list_empty(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < HIST_DEPTH; i++)
|
||||
if (sl[i][0] != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int string_list_count(void)
|
||||
{
|
||||
int i, count = 0;
|
||||
for (i = 0; i < HIST_DEPTH; i++)
|
||||
if (sl[i][0] != 0)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
static char *list_first_entry(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < HIST_DEPTH; i++)
|
||||
if (sl[i][0] != 0)
|
||||
return &sl[i][0];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void string_list_print_by_column(void)
|
||||
{
|
||||
int len = 0, num, i, j;
|
||||
|
||||
for (i = 0; i < HIST_DEPTH; i++) {
|
||||
if (sl[i][0] != 0) {
|
||||
int l = strlen(&sl[i][0]) + 4;
|
||||
if (l > len)
|
||||
len = l;
|
||||
}
|
||||
}
|
||||
|
||||
if (!len)
|
||||
return;
|
||||
|
||||
num = 80 / (len + 1);
|
||||
|
||||
for (j = 0; j < HIST_DEPTH; j++) {
|
||||
if (sl[j][0] != 0) {
|
||||
if (!(++i % num))
|
||||
printf("%s\n", &sl[j][0]);
|
||||
else
|
||||
printf("%-*s", len, &sl[j][0]);
|
||||
}
|
||||
}
|
||||
if (i % num)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void command_complete(char *instr)
|
||||
{
|
||||
struct command_struct * const *cmd;
|
||||
|
||||
for (cmd = __bios_cmd_start; cmd != __bios_cmd_end; cmd++)
|
||||
if (!strncmp(instr, (*cmd)->name, strlen(instr)))
|
||||
string_list_add((*cmd)->name);
|
||||
}
|
||||
|
||||
int complete(char *instr, char **outstr)
|
||||
{
|
||||
int pos;
|
||||
char ch;
|
||||
int changed;
|
||||
int outpos = 0;
|
||||
int reprint = 0;
|
||||
char *first_entry;
|
||||
char *entry;
|
||||
int i;
|
||||
|
||||
string_list_init();
|
||||
command_complete(instr);
|
||||
|
||||
pos = strlen(instr);
|
||||
|
||||
*outstr = "";
|
||||
if (string_list_empty())
|
||||
reprint = 0;
|
||||
else
|
||||
{
|
||||
out[0] = 0;
|
||||
|
||||
first_entry = list_first_entry();
|
||||
|
||||
while (1) {
|
||||
entry = first_entry;
|
||||
ch = entry[pos];
|
||||
if (!ch)
|
||||
break;
|
||||
|
||||
changed = 0;
|
||||
for (i = 0; i < HIST_DEPTH; i++) {
|
||||
if (sl[i][0] != 0) {
|
||||
if (!sl[i][pos])
|
||||
break;
|
||||
if (ch != sl[i][pos]) {
|
||||
changed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
break;
|
||||
out[outpos++] = ch;
|
||||
pos++;
|
||||
}
|
||||
|
||||
if ((string_list_count() != 1) && !outpos && tab_pressed) {
|
||||
printf("\n");
|
||||
string_list_print_by_column();
|
||||
reprint = 1;
|
||||
tab_pressed = 0;
|
||||
}
|
||||
|
||||
out[outpos++] = 0;
|
||||
*outstr = out;
|
||||
|
||||
if (*out == 0)
|
||||
tab_pressed = 1;
|
||||
else
|
||||
tab_pressed = 0;
|
||||
}
|
||||
|
||||
return reprint;
|
||||
}
|
6
litex/soc/software/bios/complete.h
Normal file
6
litex/soc/software/bios/complete.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef __COMPLETE_H__
|
||||
#define __COMPLETE_H__
|
||||
|
||||
int complete(char *instr, char **outstr);
|
||||
|
||||
#endif
|
|
@ -17,6 +17,7 @@
|
|||
#include <uart.h>
|
||||
|
||||
#include "readline.h"
|
||||
#include "complete.h"
|
||||
|
||||
#ifndef TERM_NO_HIST
|
||||
static int hist_max = 0;
|
||||
|
@ -191,6 +192,12 @@ int readline(char *buf, int len)
|
|||
int insert = 1;
|
||||
char ichar;
|
||||
|
||||
#ifndef TERM_NO_COMPLETE
|
||||
char tmp;
|
||||
int reprint, i;
|
||||
char *completestr;
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
|
||||
ichar = read_key();
|
||||
|
@ -200,6 +207,27 @@ int readline(char *buf, int len)
|
|||
|
||||
switch (ichar) {
|
||||
case '\t':
|
||||
#ifndef TERM_NO_COMPLETE
|
||||
buf[eol_num] = 0;
|
||||
tmp = buf[num];
|
||||
|
||||
buf[num] = 0;
|
||||
reprint = complete(buf, &completestr);
|
||||
buf[num] = tmp;
|
||||
|
||||
if (reprint) {
|
||||
printf("%s%s", PROMPT, buf);
|
||||
|
||||
if (tmp)
|
||||
for (i = 0; i < eol_num - num; i++)
|
||||
getcmd_putch(CTL_BACKSPACE);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (completestr[i])
|
||||
cread_add_char(completestr[i++], insert, &num,
|
||||
&eol_num, buf, len);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case KEY_HOME:
|
||||
|
|
Loading…
Reference in a new issue