From 3f985d706eb1b10b6071ca7b84067fe8731e0184 Mon Sep 17 00:00:00 2001 From: whowechina Date: Sat, 23 Sep 2023 11:40:30 +0800 Subject: [PATCH] cli allows abbreviation when no ambiguity --- Production/Firmware/chu_pico.uf2 | Bin 116224 -> 116736 bytes firmware/src/cmd.c | 149 ++++++++++++++++++------------- 2 files changed, 86 insertions(+), 63 deletions(-) diff --git a/Production/Firmware/chu_pico.uf2 b/Production/Firmware/chu_pico.uf2 index e3c56ed7faf1b813a206c15389650fdabd8cb83a..e99e6da490e1edc4df3ba4d677a2eecdae052003 100644 GIT binary patch delta 14602 zcmbVTd3aM*+CL{rn{Fv7DbOX9o1{y+fTb-^kfo#$T3TwsiYyfi6bMxyK&jP1T5Dxd z#15x&Dlmx1Ff0`-P-PrCQxF}IqKVtETZOSY<2ZLV>5?Yjdvdd!_US#Zo0Ls4`0iV=E{yMzSlL&>WgjDT?Z>B`vN$(KaerMca5@nZ@`fX! z_YP7cq!1XnuhnqP2>w}Tg%&8qTo;;!P{`jISYXwr@T8-2X&qpX2 z%_}`|y5d3WWu#`;TeWgot>?N-f9O|@a2*8v+bjMpxAfjQ{iVX>h7+7EYw089FK*pLV6W+Wh?bOaK* zJCS;tX$VrcR|<`73UQNbSb_Y6>^MFaB>n*$%I#5wQ3b)`v3~hp*(9K>RlL(!)05DR6f1!A$d&X014 zD`Z62$$_m!+lu#^w-wRz=kQJ92-S}AqTW{0V#bDj=09t(NE}EU;X;tXkEbVueeKRZ zVik6gXCjh@9CRR~V8;T|<(Wdo6{J04di-pM+F&vxolFQ5ulIl26JpRKtV8hYv(r&3 zrQ1PdeCoLrB(wn?1Zo1RhkuUqNbLZe>ULQ{h#2ieg1V!NJQA6*^oldSD5hdz#Xow& zQ}5Z+46bZMQfnVGTeSE%7W)T~@dvwHhgy_kuLB>G!6-rEYXjf(;E77{?~YW|aEftS z2CntUfb*@JqXy1P1GXMHaBh)5M~>1y*Du$pg&^_#pj;OPZO0(eV>ib(=&2HpA}V!w zowrg<&NMF%E)wM8BCD|4M#noNgA{Sk*Y)hOj4nT~|!a4I|7tX(X zN+H(tMvQwTN22-3P1Fe2(C#ctu~IT<0l3ls4a+JS){WPpQWGN;SiM#fma*Py>G}2W^IWeSGjx z`J!b=w`gge8H+V!@z9aVhX>fOY9)0;hduKCV83A>>Wo=B9T{Xz@?T~ls}2#+%?=l@ z^UZzStaJn{8EyCkOlW$gmsL$1I#)WM=w^WFc(G)3F=wd>=NN>@q{T^+3)RFoN~6vq#cyU|9O zZs2s}urM6$jfJl7^(YJ-AQ{8Q;C`}rcs%}rJTZLqs4x1N$88>uuYkw;nd5Hcn^RE? zc>I98H#{l+H0Uh9>5W+#`x{f#jZ~ByuN04*mX8?bzTIMe7sLiuGr1OXf5b>INWO^^ z8}r_X_2q9+!F-AlQo+3Cg?0yWc+(ViV=Sr#Z|Z)M88-v}jckgW;PLiW-1ISf2K+sN z_OO~^LmKp5E(#NmyNb;5kKpufI~KPNJd5;&zIa5X4QCU*b}X(UMcR=;PrDT2Lb661 zpZrT#dTmv0JPs<1%U_Nb&3g?-FRL=EHoHZdMM&C235Bs+oNRtyslJFwnh(c~K{g4?VenHR|Igg8u2_a%&S;}eP&Mnh6C zS(PGvZ@Zx=aZX}!oE2xK0@IZhCZ2L3BeM5))az5xJm4wCU$}9bc?nCXUFEH zR)mO;^~IIM6=qt(#HT=ige^=^h|5WbFmlE&*S3GDw=>Cl*C#zHm{Wh#d%34x7g11% z!$j&bTK){heE~3RPDDau5)!tnVSR;SE8zFRtr&@;SeM-<4jeTsN*W?j+z?rCf#~&J zu^&6@^>gQp1&l_(_(!J>rCCZK+PTw8LlnN>JD{>HI45G$JpE&0 zn!Ae0@%J<2EQ2OM&a#PtYb}r!emBFKw*c1KyrN=M55L2T)a~)$9@*6$3h^pgmpoGT zLJHZHyeP>&n293JHJM*A_jVw?qNK^JDEJNvupYqE~NOZmExZWjacg*+Yt2OgFB%?jh$@Pt6&colx)1iDZkhMpiU< z`X{5_ol=?spCeP!MyW=?*1>gezKc!!=g8_bL!Goh$cy9!!IzcdKb=g{3U|bJ;LO?{ z0$|KeCCu(Wj44#9pD8(sGR{7UWy*I5LA@3n|J(R0!BwJ{h_ZYW#SQ`>!z&gbl zGbg4X)e>I!(Uu)s3QsA;PUkS-$GiW=40E!4-*HBljMSxDGEqFNWU?IYw$2Ej=k0E# zc+x3k{Kq~7ERH!xP3A3>;z6elWMP6*d}Gksp#@khwM1wa05t)92xJ4g`W{)EF*#^x zpX**Rc{3vgA0mIsC{)DXdeH0%JX$-#8}tElTX}r>D3fSssJD{rF*DsYbGcm8=3YVS zZg42V+WA}?HkR4P6yf7bFE71-4-B!OF~v4EYfT!Mh-4@TWx};(AUGk}E^9%F$T-xN zh9&}U32Zhd*l?n}1sO9vyfWaW*-=KiU6zCOu|-&jwIBnYe9*Lbdi-dt$)BQsq0Dvf zb!SkU*a7a~E|r|+g5fYba~100aJ9_z?=$WLy%3uWwo-fZui23PYEKT@sQt+v1WCFa zw|j6hN~|$;_GEk@)iL)XOLGS#x#A|9LoRj8kIE1&ipU;&dF+L#%TX8P`y(wVW4?{0 z+0{SRoidxV`ulN;B4N5+0ho&G0MuAuiv4Ueitd|c$BB4C5QwIEBzHh^pDh?T<2{_~ z9^F*C9CVc+N%cssfW!b^wDuZ+eb})HZkQ>C&&uPJ$ab}Rh<-yM$!AyA+3P_*elWZ{ z3@4(LO4Dz9(0#tTRK-g3P%JkO$?P(S^-<4bV7JW?3PqM@^j=+EbQr}ieAR3L?q)vaF>>=i(fhh*P#a$tLa?cQb6sr)snwGab(-r*p>PIpq7C)SPpUFhDkL0QO>*P!D3;z*jx_W|SgJ|DEkmJ?uti z_gaMy2QiQLha;-o@Gx(o26{==_{p-Hz2xZl9Q+x%HQrzeb-M25Lk)iE_^tS^Qg{WEV(I*_B8+=Hk`QeR%c* zp3p*Tdp!!B9a@~fz*B&UTHkj5<*LvU*+QJ1UwS<5lu2*mBVKPV)Jc?z}-ck_l9gl1QiYAP~2*wp_ylz~nEJBA_k8A#&l`(a2uE(YdC z5cmcKQBC$wKkGsDBCIegMj-WBXupnwQ3vgu;V`T4K5BDB8+y5mY-8$0NlGMd z9a{%mqcHLQUZDb}9~&O0$O#(#Z+mvpJ{WqKp!Auyuwk+36*KJ468DAgvEkr1Q83V*ta`MCE93o6D<9aPG+&>9bPi-Yao>w}Zo1UukKw|Pr z*hB3M-p&Nl8GfnOAmwb}a?XcGvAt%wI6yv`F@iMD*hxN}5lwQ;c^)jY_-JPESK#*- zn*fI-O9@Cyy%I1_mCREE%u7LOo?nTm%6Js>-XOZN2R(^C#5*qoyZOA`0^V*uNEi5} zn$c3|(E*_sfYKtr5>b`&E*62bJXaQ-NEVgHvl`qWjz@R|<)E;njK1fo4pCM3CtI+p zS#q2R6@K?IVxB(A3!l&>9K88o-}HHoU8 zcji{v0xI?1(e(^pm3jc%z#BJ)5Ah-~)Q_&k;%1_27(sS7yhIEQ(36eRJi{06!F&l* zK8J}^H-g8lUXR=OSX*n^4e;aEEFx_8D&VM*GbJxGIWIcLXoI01i32WBjV8Od?;^?D zq3F;1Cv>9P$rt^3h`Q77R5MF*3TMf_gAr1_6O?v&m0seZ?E*>DL;lPPCG)}n^CnQ* z?KNk;*32W=-5eA1M=&d}&N4zPwtrwo?JaG{INe5s=7NYP``AgqmcAg=dCD_BU*;h+ z@7G5#J6I!rfCb}r3=(bvA>dU2&jNJ!1Cq7JJGdEu79PN!Chhx0a1yIT=sdIt&d_B= z`^`&d>_E7}I*SM`e(ah#Qi5{=5^SlIm8X#FEoLI@E#rpwem=}zsKS1)r(f|I><7sK zuY|!n7@q7MOYig`@#+37bUzvzQ#2i=e}5h8?ETxne0BWETbIupFx0YeF;+M zA(Ybyhd`{F5pa4Wwm%FzlH0H^>28N-KthCr{y>_!QZjP`k~s)y4tbSc=W!ka$ziVq zhVg@v`GW!Ghs(ky0vHw?YVzsf5+WQah+wRc+4+{aRqA$b8am1s=!g;bkzXBomIy~P zj4wh`7NFL6*au7t%7ce@B%3XVGyl9kb_me+AyV%ExzCyAAqmYx0cef_D;*7UIPevi100BDCg3dn4C>gSyr2fB%=dal_mGC=W|f9uA1onj-@T z$6ITNaFXx;Ha@+RheJLG&=+B&LxeUjCMe@V$>qWTmu&$2lvn9A-wUTeawbRid+pqvAx-}{w_s*`u|dysZ|rRRABoglg3pJj;Z zB5!vAq!;~V*DRMpFAoTP5tKggD*cgn{sBln^oE5Zu8_=E1ekv~S*A@Or#@UqbRT(l zLaYW|JdlsTQy1rHmE>tvfTym*AzJom_4rL05kB@J`a~P)9h#jBtg|52Qy>3^=xqL2 z8hC}rj;vP)c(cLQ>{GuIQGM>8I^+d1F&y5GxbA)H5@F;O!;=c!Mg^{WcU|Zb+5PD* zB7E+J`vqT;&moa7y%Lt@RX)uxL3-6M)vS?#tqA~j6@Xpmf!*X?TnFh*ckZyCyTymT z3C?eOtHMHe^LDpE+RcStFNIzo5V{+bzVRyE;hld2lDl3BboEBbd}Dz5UBLFO7aK$H z9gpB!aPggSXb8M0MW}mP#3iUHkoFQ;^j(~Pn%E?H-W1^ZyF6LUCGz%nRYdrU7sX$B ze18GwKX@g8?+MAv69Ha+0Hq)Kn?dC9{n!#c6N0PZsXY;JS%A&}5kchqJ}LQqGQh70 ze*fvM{J(fu{{+du{Sh_4kj#G(VE%7V`pF-IsCs!=KY_G2SC(2u7WKw?R>(d+MlUGz z^X3lTydR_vzjRogga96xeY=#uUn7FkNDep}NR7it3Y;1K-l&(<>p68&?X=2tRpeV| z!t`5@vl}CHwj4!U8rx7thz;w}FM|u_ndHX~&Vu*Y@J<Q^{f@i$^87@?eav>cRWZ0jBra=PLz=5LGGQ0sFqCGM^ zkqQbt30vr51&*VY^)L`UvpiJ=V}EUEwF0+NA=u-YI+Pp$S{=-UA$-{9q_EEggbiV8 zVVoLOMc{DXv42R1;;Y|nhv)D!BZ}fJ4l^bp9q6m~=?h_ar0nSz=IyiiqS0N@B*AzP3_zl^}M<8ZFJBj${vXmOR~HSw#_F9JXWjwVIoN$!zC z9YX?gio~^%ov>yV!&BD+Xm@O<{gF61Sl*=U0J~&0_CM)R)zE<0YL@6wNR&NJQ->zN z@lYm==Bl81K`Pb@0mX`DYQs4-s)`8+GMp*Ia0(ih6U^N&2Kb4=M-`8PgbHyUUFwJr z02GJIWt~R)X&f#YYK1L1%N9eeV&EG1Sz0Ky^fd#HqN)TOp5|Rd?yNMdTE6P_Rd-ey zmfczU=N>o|0t^swc8E2dh#XuPXUjS%fw=8(BnCZFP#7BaXX<71J-7EQ^)!s z*dKq~lLv>E0(=MKwTD+Cb?h?&nfRAM+M>sq_#nNc$M-?gr^hMy3e_cY8Ec4?G2t?% z)rojK&ZQ?3act;FD2bHf6=o+Sa~)1qMjY<@D#i})D-?5TOqZZIlErh$_yPPc`b9F< z;obCJGER+@Csvx++cyTgB884I;xzmgU1-Gdo*YvHhK3REN{kph(S!A&knO=9*iq<$ z+~16p!f}QRj_o~;lGC``VagsUsXbg$1NY_+V4VWC1<6iq_-9Wwe0Nj<1MMIT1@>hM z5*58{$K9Mv52QiW4$x21@Mu}0K%Hq=Plb$tyvJbwL-c!eQwBE36aw9wfwxiJ7_Pij zl^M|KV{o2cA;4Q%IL}uAZHALu1T9S6r3kA_0g0$_&@abeJ#*L(?a-b9b%)F#pM5EG zaU5CsV-N7hWa6~oO9TI4*Gn?7bW%edV*_fJiI=2T!W$-qtzOq;2${V@W-k?BTr2}# zkPTkGK4I;Ui5ua28pd5k2Q#sO3R#e+_YjV%astq2VIguW)C|gsHpAQ3t}c2g3vZ!9 z4p$t_KB@ToK*>8;X>|@R{kiF z2Lb|5!u!+mx{$g69)Au3fe?9fVAt$l7sy##*+nN!hUwTp*-Q-xIT^n}byGdvOC8e! z08eFj@_0P2NqAlZ&;CN>F*OsXMpZKcf|zh_+)fW52Fm-7frf&AV8V;3ZU!FZDEv8S5UF(&|1F;gnxd{I?tK(G>~P|7K2j!D6e1q3T)YV$m5)bU_Ika|z${|Iaz56Z zQmi)vVwK}JlubtTpL-t+P~#F@%#Fng96r+9T@RRx%oD9Jo#*20`cuel@gm)^1V14- zxUnOhGNlyX9B9b5*uar2I+y7xIy!ZY1p-War;gQtCv3`#jK|AMa6W_o@q7qe}2$u zi9~+1jr3UyPQ?@G8y37yF<~%e2NkNgj-{%{1CUnXsrU>%U4_?B;c=W7{j!74eU}3n zx-GsmOW%=jzr*2P{*1wcu*7Z3>Qe|$yllB*OMRzB#lfo%aKDDW^*A0Dp5`-5qV~t} z15{WGi2d`tH30EiJVTaog}%EMucU(2H=x%C^sAK(=nY)nns+7W?{d&-^#-O^&8bmU zO+c_}rcmPx@=!fNqY_}VHPrS;jZv()X+DpPFo zT3>ysYBL|*@f1#^!e%_VF0&n_O|;2Tc>X@+D7!puK zWB2E0m?CUR-IC1UmL=FU#gZh}uEj$Rc@w(jo1*9IW=r%?b0wBK^`bw%qs2JWTlmRUO z>V&rpYB*b~{*Wf`#9y(A15UJX)P2BXRrrvr0&<0-VJOM9Ddc7RjI0v{;ZXD%ei?5H zc}7l!UHC3H?d-<>uMrBCZm1NNZrr$HLp55tb~U4PR-Ls=*Rt!;>^iarsV~5}52Il2 z+RNixr$_H6Ps?OK0_}$5rev@^B(-(w;qZeo{u|}~7a8L>)FSm3aQgoz_)5cT>>FHE z)yx&fEB?Qx6WsH9TMdP|Mi;bje&x&_U8cpn-9kS27r3~w|WYC zz2@hIp^lfaR_(nTm>nAtG=$)hG^rVHjN1%{mF$0eeBH3UuEKNunYhWc;4(ec49`<% zFVioZaT-_U7H%@w^D>6Ha}O5ko`(mR+xwCF10Z&N6xt@B44^OJ_eVgbuOjt$pe?|w z^t1`khIy`kf@hH~ASV9~cwIo99vR~u^6=R8&uF@z0ZJ>5BK0+(AlUwX4|L_Yly~YI zNIeB;F3>|Kk@}T3iN6c3eHl)pisWT!M5{bptC?s`R7yv{MkUsZ_>0Ds9N5Y zcS>6DE=(Q!xJj7kaGAbU21f%x%|K01@a@p_^Y zi}T@Qp1;y52k;0wbw8e}nds`*2csbf8DLwf+YMXGT>8>}oFa>G(MboeDY((YFY?s<9UgQ$7NQioxLSPl`TRI5(naWz=%Qoa#%pjVef4e3 zgMF6=`wk0m7H9e%={<)lOU~l8Ie%Ua$MD=f?G<<*&Ho-&75E!J#LWP6Z%g^y=JMf< zzke~%c+E?JzX#zliq~KI5}o=ko-Mn1fj<8(j+>YW8-r@tAZ!L|0%`$j1v&@R1(XQI zhR`SvPAJRR`#{gXN_y*EoJ70M;p@^)=l6U)e#h!@4oAaN_qcP|kaE5mvVebMp&jYD zX4{Tjc+{N?)CvE!LX9F|QX2M7^Eq4qlhq%%jsbq@JEgzJJ28u;`C2N;*Wl25N57-H zfNx+jfQM4mMGlFduel>x-Qld*80e0f3nhCW&hIX5L+bOp;44WvfZQYX!Cgh>y0^mq E2Sx_2Q2+n{ delta 14279 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 CI+!B> diff --git a/firmware/src/cmd.c b/firmware/src/cmd.c index 4bcdc14..aad0723 100644 --- a/firmware/src/cmd.c +++ b/firmware/src/cmd.c @@ -15,7 +15,6 @@ #define SENSE_LIMIT_MIN -7 #define MAX_COMMANDS 20 -#define MAX_COMMAND_LENGTH 20 #define MAX_PARAMETERS 5 #define MAX_PARAMETER_LENGTH 20 @@ -23,32 +22,47 @@ const char *chu_prompt = "chu_pico>"; typedef void (*cmd_handler_t)(int argc, char *argv[]); -typedef struct { - char name[MAX_COMMAND_LENGTH]; - cmd_handler_t handler; -} command_t; +static const char *commands[MAX_COMMANDS]; +static cmd_handler_t handlers[MAX_COMMANDS]; +static int num_commands = 0; -command_t commands[MAX_COMMANDS]; -int num_commands = 0; - -static void register_command(char *name, cmd_handler_t handler) +static void register_command(const char *cmd, cmd_handler_t handler) { if (num_commands < MAX_COMMANDS) { - strcpy(commands[num_commands].name, name); - commands[num_commands].handler = handler; + commands[num_commands] = cmd; + handlers[num_commands] = handler; num_commands++; } } +// return -1 if not matched, return -2 if ambiguous +static int match_prefix(const char *str[], int num, const char *prefix) +{ + int match = -1; + bool found = false; + + for (int i = 0; (i < num) && str[i]; i++) { + if (strncmp(str[i], prefix, strlen(prefix)) == 0) { + if (found) { + return -2; + } + found = true; + match = i; + } + } + + return match; +} + static void handle_help(int argc, char *argv[]) { printf("Available commands:\n"); for (int i = 0; i < num_commands; i++) { - printf("%s\n", commands[i].name); + printf("%s\n", commands[i]); } } -static void list_colors() +static void disp_colors() { printf("[Colors]\n"); printf(" Key upper: %06x, lower: %06x, both: %06x, off: %06x\n", @@ -57,7 +71,7 @@ static void list_colors() printf(" Gap: %06x\n", chu_cfg->colors.gap); } -static void list_style() +static void disp_style() { printf("[Style]\n"); printf(" Key: %d, Gap: %d, ToF: %d, Level: %d\n", @@ -65,31 +79,31 @@ static void list_style() chu_cfg->style.tof, chu_cfg->style.level); } -static void list_tof() +static void disp_tof() { printf("[ToF]\n"); printf(" Offset: %d, Pitch: %d\n", chu_cfg->tof.offset, chu_cfg->tof.pitch); } -static void list_sense() +static void disp_sense() { printf("[Sense]\n"); - printf(" Global: %d, debounce (touch, release): %d, %d\n", chu_cfg->sense.global, + printf(" Global: %+d, debounce (touch, release): %d, %d\n", chu_cfg->sense.global, chu_cfg->sense.debounce_touch, chu_cfg->sense.debounce_release); printf(" | 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|16|\n"); - printf(" -------------------------------------------------\n"); + printf(" ---------------------------------------------------\n"); printf(" A |"); for (int i = 0; i < 16; i++) { - printf("%2d|", chu_cfg->sense.keys[i * 2]); + printf("%+2d|", chu_cfg->sense.keys[i * 2]); } printf("\n B |"); for (int i = 0; i < 16; i++) { - printf("%2d|", chu_cfg->sense.keys[i * 2 + 1]); + printf("%+2d|", chu_cfg->sense.keys[i * 2 + 1]); } printf("\n"); } -static void list_hid() +static void disp_hid() { printf("[HID]\n"); printf(" Joy: %s, NKRO: %s.\n", @@ -97,35 +111,43 @@ static void list_hid() chu_cfg->hid.nkro ? "on" : "off" ); } -void handle_list(int argc, char *argv[]) +void handle_display(int argc, char *argv[]) { - const char *usage = "Usage: list [colors|style|tof|sense|hid]\n"; + const char *usage = "Usage: display [colors|style|tof|sense|hid]\n"; if (argc > 1) { printf(usage); return; } if (argc == 0) { - list_colors(); - list_style(); - list_tof(); - list_sense(); - list_hid(); + disp_colors(); + disp_style(); + disp_tof(); + disp_sense(); + disp_hid(); return; } - if (strcmp(argv[0], "colors") == 0) { - list_colors(); - } else if (strcmp(argv[0], "style") == 0) { - list_style(); - } else if (strcmp(argv[0], "tof") == 0) { - list_tof(); - } else if (strcmp(argv[0], "sense") == 0) { - list_sense(); - } else if (strcmp(argv[0], "hid") == 0) { - list_hid(); - } else { - printf(usage); + const char *choices[] = {"colors", "style", "tof", "sense", "hid"}; + switch (match_prefix(choices, 5, argv[0])) { + case 0: + disp_colors(); + break; + case 1: + disp_style(); + break; + case 2: + disp_tof(); + break; + case 3: + disp_sense(); + break; + case 4: + disp_hid(); + break; + default: + printf(usage); + break; } } @@ -153,26 +175,23 @@ static void handle_fps(int argc, char *argv[]) static void handle_hid(int argc, char *argv[]) { - const char *usage = "Usage: hid \n"; + const char *usage = "Usage: hid \n"; if (argc != 1) { printf(usage); return; } - if (strcmp(argv[0], "joy") == 0) { - chu_cfg->hid.joy = 1; - chu_cfg->hid.nkro = 0; - } else if (strcmp(argv[0], "nkro") == 0) { - chu_cfg->hid.joy = 0; - chu_cfg->hid.nkro = 1; - } else if (strcmp(argv[0], "both") == 0) { - chu_cfg->hid.joy = 1; - chu_cfg->hid.nkro = 1; - } else { + const char *choices[] = {"joy", "nkro", "both"}; + int match = match_prefix(choices, 3, argv[0]); + if (match < 0) { printf(usage); return; } + + chu_cfg->hid.joy = ((match == 0) || (match == 2)) ? 1 : 0; + chu_cfg->hid.nkro = ((match == 1) || (match == 2)) ? 1 : 0; config_changed(); + disp_hid(); } static int extract_non_neg_int(const char *param, int len) @@ -218,7 +237,7 @@ static void handle_tof(int argc, char *argv[]) chu_cfg->tof.pitch = pitch; config_changed(); - list_tof(); + disp_tof(); } static uint8_t *extract_key(const char *param) @@ -282,7 +301,7 @@ static void handle_sense(int argc, char *argv[]) slider_update_config(); config_changed(); - list_sense(); + disp_sense(); } static void handle_debounce(int argc, char *argv[]) @@ -314,7 +333,7 @@ static void handle_debounce(int argc, char *argv[]) slider_update_config(); config_changed(); - list_sense(); + disp_sense(); } static void handle_save() @@ -331,7 +350,7 @@ static void handle_factory_reset() void cmd_init() { register_command("?", handle_help); - register_command("list", handle_list); + register_command("display", handle_display); register_command("fps", handle_fps); register_command("hid", handle_hid); register_command("tof", handle_tof); @@ -346,24 +365,28 @@ static int cmd_len = 0; static void process_cmd() { - char *command; char *argv[MAX_PARAMETERS]; int argc; - command = strtok(cmd_buf, " \n"); + char *cmd = strtok(cmd_buf, " \n"); argc = 0; while ((argc < MAX_PARAMETERS) && (argv[argc] = strtok(NULL, " \n")) != NULL) { argc++; } - for (int i = 0; i < num_commands; i++) { - if (strcmp(commands[i].name, command) == 0) { - commands[i].handler(argc, argv); - printf("\n"); - break; - } + int match = match_prefix(commands, num_commands, cmd); + if (match == -2) { + printf("Ambiguous command.\n"); + return; } + if (match == -1) { + printf("Unknown command.\n"); + handle_help(0, NULL); + return; + } + + handlers[match](argc, argv); } void cmd_run()