Skip to content

Commit

Permalink
bios: add auto completion for commands
Browse files Browse the repository at this point in the history
  • Loading branch information
fjullien committed Apr 29, 2020
1 parent b6a5332 commit 6643bb9
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 0 deletions.
6 changes: 6 additions & 0 deletions litex/soc/software/bios/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions litex/soc/software/bios/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
174 changes: 174 additions & 0 deletions litex/soc/software/bios/complete.c
Original file line number Diff line number Diff line change
@@ -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 changes: 6 additions & 0 deletions litex/soc/software/bios/complete.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef __COMPLETE_H__
#define __COMPLETE_H__

int complete(char *instr, char **outstr);

#endif
28 changes: 28 additions & 0 deletions litex/soc/software/bios/readline.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <uart.h>

#include "readline.h"
#include "complete.h"

#ifndef TERM_NO_HIST
static int hist_max = 0;
Expand Down Expand Up @@ -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();
Expand All @@ -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:
Expand Down

0 comments on commit 6643bb9

Please sign in to comment.