Neben der Fähigkeit Random Access Files handzuhaben vermisse ich nur eine Sache bei PBASIC:
Es gibt keine Befehlszeile in der man mal eben schnell einen Term ausrechnen kann ohne ein Programm schreiben zu müssen.
Glücklicherweise bietet PBASIC den Befehl EVAL, mit dem eine beliebige Zeichenkette interpretiert werden kann. Also schrieb ich mir ein „kleines“ BASIC-Programm, dass einen Zeileneditor mit Hot-key Funktionen bietet. Die hier entstandene Zeichenkette wird dann mit dem Befehl EVAL ausgeführt und das Programm kehrt zum Zeileneditor zurück.
Als ich das Programm schrieb, wusste ich noch nicht wie man Portfolios eingebauten (AES) Zeileneditor programmiert, sonst hätte ich BIOS-CALLS verwendet. In diesem Beispiel wurde alles mit normalen BASIC-Befehlen für Zeichenkettenmanipulation realisiert, dadurch ist es natürlich ein wenig langsam und entspricht nicht zu 100% dem AES Zeileneditor, ich habe aber versucht alles identisch zu machen und bin mit dem Ergebnis recht zufrieden.
Wozu das ganze? Nun, ich will häufig nur mal eben kurz einen Term lösen und in Abhängigkeit des Ergebnisses die eine oder andere Variable ändern. Natürlich könnte man ein Programm mit dem Editor schreiben und mit ALT_R ausführen. Wenn ich dann aber einen Wert öndern will, muss ich PBASIC wieder verlassen, das Programm ändern und PBASIC erneut aufrufen. Das wird auf dauer lästig und kostet Zeit. Wenn ich mit PBASIC „reden“ kann wärend es läuft, geht das schneller.
Ich starte PBASIC CMDLIN, wenn CMDLIN geladen ist erschient die Titelleiste und eine Zeile darunter das „ok.“. CMDLIN ist bereit.
z.B.: 20 durch 3 Teilen.
? 20/3 6,66666 ok.
CMDLIN (bzw. PBASIC) liefert das Ergebnis und bestätigt die bereitschaft mit einem „ok.“
Na gut, das kann jeder Taschenrechner. Aber was ist, wenn die Aufgabe etwas komplexer ist?
? (20/3+5/4)*(20-2/3) 153,0555560704444 ok.
wenn ich das mit einem Taschenrechner lösen will, brauche ich wahrscheinlich noch einen Zettel und einen Stift Und sollte ich einen Fehler machen, muss ich von vorn beginnen.
Mit PBasic kann ich mir die Aufgabe nochmal genau ansehen und evtl. ändern, bevor ich die Eingabe-Taste drücke.
Wenn ich einen Wert ändern, oder die Aufgabe erweitern möchte, drücke ich Fn_1, und die Zeile wird wieder dargestellt, mit der Möglichkeit sie zu bearbeiten.
Fn1
? (19/3+5/4)*(19-2/3)/5 27,80555644444444 ok.
Es lassen sich natürlich auch Variablen und Funktionen definieren und lange Aufgaben über mehrere Zeilen lösen. Mit dem Befehl EVAL lassen sich Zeichenketten „interpretieren“
z.B: Ich möchte meine Benzin-Kosten für diesen Monat ermitteln. Die können aber je nach Benzinpreis stark variieren. Ich mache dann ein „Was ist Wenn“ -Spiel.
Ich fahre jeden Werktagtag 32 Kilometer, mein Wagen verbraucht 7 Liter auf 100 km:
Ich tippe folgende Zeilen ein:
TERM$="Kosten=(20*32/100)*7*Preis:?Kosten" Preis=1,49 EVAL TERM$
Um die Kosten bei einem höheren Preis zu ermitteln gebe ich z.B Preis=1,52 ein und dann EVAL TERM$. Dieses Spielchen kann man so oft wiederholen wie man will, ohne PBASIC zu verlassen.
Es lassen sich nicht nur Rechenaufgaben lösen, fast alle PBASIC Befehle , außer Grafik, lassen sich anwenden, die Befehlszeile hat allerdings eine maximale Länge von 40 Zeichen.
Da ich Portfolios Zeileneditor möglichst treu nachahmen wollte, brauchte ich natürlich Hot-Keys um in der Zeile herumspringen zu können. Da ich schon mal dabei war habe ich gleich noch ein paar weitere Hot-Keys als Makros definiert um die Tipparbeit zu reduzieren:
Macros:
Tastenkombination | Text |
---|---|
Alt_A | ABS( |
Alt_B | BIN$( |
Alt_H | HEX$( |
Alt_I | INT( |
Alt_K | KILL „ |
Alt_L | LOG( |
Alt_P | |
Alt_R | RUN „ |
Alt_S | SQR( |
Alt_V | VAL( |
Hot-keys:
Tastenkombination | Wirkung |
---|---|
Alt_C | CLS, löscht den Bildschirm |
Alt_E | END, beendet CMDLIN (und PBASIC) |
Alt_F | FILES, listet alle Dateien im aktuellen Verzeichnis |
Alt_M | MENU, öffnet ein Menü mit allen *.BAS Dateien im aktuellen Verzeichnis. |
Alt_N | NEW, löscht den Speicher (verlässt und lädt CMDLIN erneut) |
CMDLIN kann keine Grafik, sollten sie versehentlich SCREEN 8 eingeben wird der Bildschirm unlesbar, bzw. CMDLIN kann nicht richtig ausgeführt werden.
Vermeiden sie es irgendeinen der folgenden Befehle zu verwenden:
Der Befehl MENU wird von CMDLIN anders genutzt (siehe Alt_M). Obwohl CMDLIN keine Grafik unterstützt, können PGC-Files im Menü angezeigt werden, der Befehl schaltet selbständig zwischen den Bildschirm-Modi hin und her.
CMDLIN hat zwei eigene Befehle, die nicht von PBASIC stammen:
Tasten zum editieren der Zeile:
Funktion | Tastenkombination |
---|---|
Cursor nach links | ← |
Cursor nach rechts | → |
Cursor ein Wort nach links | Ctrl_← |
Cursor ein Wort nach rechts | Ctrl_→ |
Cursor an Zeilenanfang | Shift_← |
Cursor an Zeilenende | Shift_→ |
nach rechts löschen | Del |
nach links löschen | BS |
ein Wort nach rechts löschen | Ctrl_RShift_BS |
ein Wort nach links löschen | Ctrl_BS |
bis Zeilenanfang löschen | Shift_BS |
bis Zeilenende löschen | RShift_LShift_BS |
Shift_Del schaltet den Tastaturmodus zwischen Einfügen und Überschreiben hin und her.
Fn_1 holt die letzte Zeile zurück.
Wenn die Meldung „command line error“ erscheint, ist ein Fehler in CMDLIN.BAS aufgetreten, nicht in der Zeile die sie getippt haben. Alle anderen Fehlermeldungen beziehen sich auf die Zeile die sie getippt haben.
Der Code: Auffalend ist, dass alle Varaiblen mit „XX“ anfangen. Dies wurde gemacht, um zu verhindern, dass Variablen im Programm durch Variablen des Benutzers überschrieben werden. Ich hielt es für unwarscheinlich, dass jemand Variablen benutzt die mit „XX“ anfangen.
XXM0=FRE(0):XXSO=SHIFT:SSIZE=40:GOTO 1000 10 ? "ok" ON ERROR GOTO 400 XXCP=(CSRLIN-1)*40:XXHK=0 ? @XXCP,XXCM$; 15 IF SHIFT<>XXS1 THEN GOSUB 17 IF XXIT>XXTO THEN 29 XXIK$=INKEY$:IF XXIK$="" THEN XXIT=XXIT+1:GOTO 15 XXIT=0 IF XXS1=SHIFT THEN XXHK=0 XXCAP=VAL(MID$(BIN$(SHIFT),2,1)) IF LEN(XXIK$)>1 THEN 25 IF ASC(XXIK$)<31 OR ASC(XXIK$)>126 THEN 20 XXCL$=XXCL$+XXIK$:XXCP=XXCP+1:? @XXCP-1,XXIK$; ? @XXCP,XXCR$" ";:? @XXCP,""; XXCM$=XXCL$+XXCR$:GOTO 15 17 XXS1=16*INT(SHIFT/16):XXHK=SHIFT-XXS1 RETURN 20 REM SINGLESTROKE KEYS IF XXIK$=CHR$(8) THEN 200 IF XXIK$=CHR$(127) AND (XXHK=1 OR XXHK=2) THEN 235 IF XXIK$=CHR$(127) THEN 220 IF XXIK$=CHR$(13) THEN ? "": GOTO 90 IF XXIK$=CHR$(27) THEN 300 GOTO 15 25 REM DOUBLESTROKE KEYS IF XXIK$="KK" THEN 100 IF XXIK$="MM" THEN 110 IF XXIK$="ss" THEN 140 IF XXIK$="tt" THEN 150 IF XXIK$="GG" THEN 120 IF XXIK$="OO" THEN 130 IF XXIK$=";;" AND POS(0)=1 THEN 350 IF XXIK$="SS" THEN 210 IF XXIK$="RR" THEN 430 IF XXIK$=STRING$(2,30) THEN XXMAC$="ABS(":GOTO 260 IF XXIK$=STRING$(2,48) THEN XXMAC$="BIN$(":GOTO 260 IF XXIK$=STRING$(2,46) AND POS(0)=1 THEN XXMAC$="CLS":GOTO 270 IF XXIK$=STRING$(2,33) AND POS(0)=1 THEN XXMAC$="FILES":GOTO 270 IF XXIK$=STRING$(2,35) THEN XXMAC$="HEX$(":GOTO 260 IF XXIK$=STRING$(2,23) THEN XXMAC$="INT(":GOTO 260 IF XXIK$=STRING$(2,37) THEN XXMAC$="KILL "+CHR$(34):GOTO 260 IF XXIK$=STRING$(2,38) THEN XXMAC$="LOG(":GOTO 260 IF XXIK$=STRING$(2,50) THEN 310 IF XXIK$=STRING$(2,24) AND POS(0)=1 THEN GOTO 350 IF XXIK$=STRING$(2,25) THEN XXMAC$="PRINT ":GOTO 260 IF XXIK$=STRING$(2,18) THEN XXMAC$="EVAL ":GOTO 260 IF XXIK$=STRING$(2,19) THEN XXMAC$="RUN "+CHR$(34):GOTO 260 IF XXIK$=STRING$(2,31) THEN XXMAC$="SQR(":GOTO 260 IF XXIK$=STRING$(2,47) THEN XXMAC$="VAL(":GOTO 260 IF XXIK$=STRING$(2,49) AND POS(0)=1 THEN XXMAC$="NEW":GOTO 270 GOTO 15 29 IF XXOT=0 THEN 15 OFF:XXIT=0:GOTO 15 90 REM EVAL XXC$=UCASE$(XXCM$) IF XXCM$<>"" THEN XXOC$=XXCM$ IF XXC$="FILES" THEN 340 IF XXC$="MENU" THEN 310 IF INSTR(XXC$,"EVAL ")<>0 THEN GOSUB 450 IF XXC$="NEW" THEN 170 IF XXC$="END" THEN 300 XXELD=1:EVAL XXCM$:XXELD=0 95 XXCM$="":XXCL$="":XXCR$="" XXTO=XXLT*XXOT:GOTO 10 100 REM MOVE CURSOR TO THE LEFT IF POS(0)<2 THEN 15 IF XXINS=0 THEN 200 IF XXHK=1 OR XXHK=2 THEN 120 IF XXHK=4 THEN 140 XXCP=XXCP-1:? @XXCP,"";:GOTO 160 110 REM MOVE CURSOR TO THE RIGHT IF XXINS=0 OR POS(0)>LEN(XXCM$) THEN 15 IF XXHK=1 OR XXHK=2 THEN 130 XXCP=XXCP+1:? @XXCP,"";:GOTO 160 120 REM MOVE CURSOR TO START OF LINE IF XXINS=0 THEN 240 XXCP=(CSRLIN-1)*40 XXCL$="":XXCR$=XXCM$ ? @XXCP,"";:GOTO 15 130 REM MOVE CURSOR TO END OF LINE IF XXINS=0 THEN 15 XXCP=(CSRLIN-1)*40+LEN(XXCM$) XXCR$="":XXCL$=XXCM$ ? @XXCP,"";:GOTO 15 140 REM MOVE CURSOR ONE WORD BACK IF XXINS=0 THEN 220 IF POS(0)<2 THEN 15 XXI=POS(0)-2 142 XXI=XXI-1:IF XXI<1 THEN 145 XXX$=MID$(XXCM$,XXI,1) IF XXX$=" " THEN 145 IF XXX$=CHR$(34) OR XXX$="/" THEN 145 GOTO 142 145 XXCP=(CSRLIN-1)*40+XXI:? @XXCP,""; GOTO 160 150 REM MOVE CURSOR ONE WORD TO THE RIGHT IF XXINS=0 OR POS(0)>LEN(XXCM$) THEN 15 XXI=POS(0) 152 XXI=XXI+1:IF XXI>LEN(XXCM$)-1 THEN 155 IF MID$(XXCM$,XXI,1)=" " THEN 155 IF MID$(XXCM$,XXI,1)=CHR$(34) THEN 155 GOTO 152 155 XXCP=(CSRLIN-1)*40+XXI:? @XXCP,""; GOTO 160 160 XXCL$=LEFT$(XXCM$,POS(0)-1) XXCR$=RIGHT$(XXCM$,LEN(XXCM$)-POS(0)+1) GOTO 15 170 REM NEW IF NOT EXISTS("C:\CMDLIN.BAS") THEN 171 RUN "C:\CMDLIN.BAS" 171 IF NOT EXISTS("A:\BASIC\CMDLIN.BAS") THEN 172 RUN "A:\BASIC\CMDLIN.BAS" 172 IF NOT EXISTS("A:\CMDLIN.BAS") THEN 173 RUN "A:\CMDLIN.BAS" 173 ? CHR$(13)"couldn't find CMDLIN.BAS" XXCL$="":XXCM$="":XXCR$="":XXOC$="" GOTO 10 200 REM BACKSPACE IF XXHK=3 THEN 250 IF XXHK=2 THEN 240 IF XXHK=1 THEN 210 IF POS(0)<2 THEN 15 XXCL$=LEFT$(XXCL$,LEN(XXCL$)-1) XXCP=XXCP-1:? @XXCP,XXCR$" ";:? @XXCP,""; XXCM$=XXCL$+XXCR$:GOTO 15 210 REM DEL IF XXINS=0 OR POS(0)>LEN(XXCM$) THEN 15 IF XXHK=5 OR XXHK=6 THEN 250 XXCR$=RIGHT$(XXCR$,LEN(XXCR$)-1) XXCM$=XXCL$+XXCR$:? @XXCP,XXCR$" "; ? @XXCP,"";:GOTO 15 220 REM BS WORD IF XXINS=1 AND (XXHK=5 OR XXHK=6) THEN 230 IF POS(0)<2 THEN 15 XXI=POS(0)-2 222 XXI=XXI-1:IF XXI<1 THEN 225 XXX$=MID$(XXCM$,XXI,1) IF XXX$=" " OR XXX$="/" OR XXX$=":" THEN 225 IF XXX$=CHR$(34) THEN 225 GOTO 222 225 XXCL$=LEFT$(XXCL$,XXI) XXCP=(CSRLIN-1)*40+XXI ? @XXCP,SPACE$(39-LEN(XXCL$)); ? @XXCP,XXCR$;:XXCM$=XXCL$+XXCR$ ? @XXCP,"";:GOTO 15 230 REM DEL WORD IF XXINS=0 OR POS(0)>LEN(XXCM$) THEN 15 XXI=POS(0) 232 XXI=XXI+1:IF XXI>LEN(XXCM$)-1 THEN 235 XXX$=MID$(XXCM$,XXI,1) IF XXX$=" " OR XXX$=CHR$(34) THEN 235 GOTO 232 235 XXCR$=RIGHT$(XXCM$,(LEN(XXCM$)-XXI)) ? @XXCP,SPACE$(39-LEN(XXCL$)); ? @XXCP,XXCR$;:XXCM$=XXCL$+XXCR$ ? @XXCP,"";:GOTO 15 240 REM BACKSPACE TO START OF LINE IF XXHK=5 OR XXHK=6 THEN 250 XXCP=(CSRLIN-1)*40:? @XXCP,SPACE$(39); ? @XXCP,XXCR$;:? @XXCP,""; XXCM$=XXCR$:XXCL$="":GOTO 15 250 REM DEL TO END OF LINE ? SPACE$(LEN(XXCR$)); XXCR$="":? @XXCP,""; XXCM$=XXCL$:GOTO 15 260 IF XXCAP=0 THEN XXMAC$=LCASE$(XXMAC$) XXCL$=XXCL$+XXMAC$:XXCM$=XXCL$+XXCR$ ? XXMAC$;XXCR$; XXCP=40*(CSRLIN-1)+LEN(XXCL$) ? @XXCP,"";:XXHK=0:GOTO 15 270 IF XXCAP=0 THEN XXMAC$=LCASE$(XXMAC$) XXCM$=XXMAC$:? XXCM$; XXCP=40*(CSRLIN-1)+LEN(XXCM$) ? @XXCP,"":XXHK=0:GOTO 90 300 REM END IF XXCP/40<>CEIL(XXCP/40) THEN PRINT ? "Bye.";:CHDIR XXORG$:SHIFT=XXSO:END 310 REM MENU ? "reading directory..."; XXCL$="":XXCM$="":XXCR$="" IF XXSFN$="$" THEN 311 DIM XXFN$(50),XXFS(50) XXM0=FRE(0)+10464 311 XXFN$(0)="Files" XXFN$(1)=FINDFILE$("*.*") XXFS(1)=FILESIZE XXFS(0)=XXFS(1) FOR XXI=2 TO 50 XXFN$(XXI)=FINDNEXT$ IF XXFN$(XXI)="" THEN XXI=XXI-1:GOTO 312 XXFS(XXI)=FILESIZE XXFS(0)=XXFS(0)+XXFS(XXI) NEXT XXI 312 REM END OF LIST CLS:? "PBASIC Ver 5.0 (C) 1991 BJ Gleason" ? XXM0" bytes free RAM " ? CWD$ ? XXFS(0)" bytes in "XXI" files"; 313 XXMC=MENU(2,25,5,0,0,-XXI-1,XXFN$(0)) IF XXMC=-1 THEN 330 IF XXMC>255 THEN XXMC=(XXMC%256) XXSFN$=XXFN$(XXMC+1) IF RIGHT$(XXSFN$,3)="BAT" THEN 314 IF RIGHT$(XXSFN$,3)="BAS" THEN 318 IF RIGHT$(XXSFN$,3)="PGC" THEN 320 IF RIGHT$(XXSFN$,3)="PGF" THEN 322 IF RIGHT$(XXSFN$,3)="FPX" THEN 322 ERRWIN 5,4,"can't execute." GOTO 313 314 REM BAT EXIT$=XXSFN$:EXITCMD EXIT$ 318 REM BAS CLS:RUN XXSFN$ 320 SCREEN 8:PGLOAD XXSFN$:WAIT SCREEN 7:GOTO 312 322 SCREEN 8:DEF SEG=&HB000 BLOAD XXSFN$,0:REFRESH WAIT:SCREEN 7:GOTO 312 330 REM QUIT MENU XXCL$="":XXCM$="":XXCR$="":XXC$="" XXSFN$="$":XXOC$="MENU":CLS:GOTO 10 340 REM FILES XXCAP=VAL(MID$(BIN$(SHIFT),2,1)) XXFSIZE=0:XXCLIN=CSRLIN XXNOM$=FINDFILE$("*.*") FOR XXI=1 TO 100 IF XXI/7=CEIL(XXI/7) THEN GOSUB 345 XXCL=XXCLIN+XXI IF XXCL>8 THEN XXCL=8 : PRINT FOR XXJ=1 TO 2 XXNM$=LEFT$(XXNOM$,LEN(XXNOM$)-4)+SPACE$(12-LEN(XXNOM$))+RIGHT$(XXNOM$,4) IF XXCAP=0 THEN XXNM$=LCASE$(XXNM$) XXFS$=RIGHT$("000"+STR$(FILESIZE),5) XXFSIZE=XXFSIZE+FILESIZE LOCATE XXCL-1,(XXJ-1)*21+1 : ? XXNM$ LOCATE XXCL-1,(XXJ-1)*21+14 : ? XXFS$ XXNOM$=FINDNEXT$ IF XXNOM$="" THEN 342 NEXT XXJ NEXT XXI 342 IF (XXI % 7)>2 OR XXI<7 THEN GOSUB 345 XXX$=" FILES "+STR$(XXFSIZE)+" BYTES" IF XXCAP=0 THEN XXX$=LCASE$(XXX$) LOCATE XXCL,8 : ? 2*(XXI-2)+XXJ+2""XXX$; ? "":XXCL$="":XXCR$="":XXCM$="":GOTO 10 345 REM WAIT IF XXI<6 THEN RETURN XXIK$=INKEY$:IF XXIK$<>"" THEN 348 XXIT=XXIT+1:IF XXIT>(XXOT*14) THEN OFF:GOTO 347 GOTO 345 347 XXIT=0:GOTO 345 348 XXIT=0:RETURN 350 REM OLD COMMAND LINE IF RIGHT$(XXOC$,1)=CHR$(13) THEN 355 ? XXOC$;:XXCL$=XXOC$:XXCR$="":XXCM$=XXOC$ XXCP=(CSRLIN-1)*40+LEN(XXCL$):GOTO 15 355 XXCM$=LEFT$(XXOC$,LEN(XXOC$)-1) IF MID$(BIN$(SHIFT),2,1)="0" THEN XXCM$=LCASE$(XXCM$) ? XXCM$;:GOTO 10 400 REM ERROR HANDLING IF ERR=38 THEN 350 XXX$="command line error " IF XXELD=0 THEN ? XXX$:GOTO 10 IF XXEH=0 THEN 410 XXEL$=" [line "+STR$(ERL)+"]" ? @(CSRLIN-1)*40,XXEL$ XXX$="error "+STR$(ERR)+" at "+STR$(PROGLOC+ERADR)) ? @(CSRLIN-1)*40,XXX$ XXCM$="":XXCL$="":XXCR$="" XXEL$="":RESUME 10 410 ? @(CSRLIN-1)*40,ERMSG$ XXCM$="":XXCL$="":XXCR$="" XXEL$="":RESUME 10 430 REM TOGGLE INS XXINS=ABS(XXINS-1) IF XXINS=1 OR XXCR$="" THEN 435 ? @(CSRLIN-1)*40+LEN(XXCL$),SPACE$(LEN(XXCR$)); XXCR$="":XXCM$=XXCL$ 435 XXS1=16*INT(SHIFT/16) XXCP=(CSRLIN-1)*40+LEN(XXCL$):? @XXCP,""; GOTO 15 450 REM EVAL "EVAL..." XXI=INSTR(XXC$,"EVAL "):XXJ=XXI+6 451 IF MID$(XXC$,XXJ,1)="$" THEN 457 IF MID$(XXC$,XXJ,1)=CHR$(34) THEN 457 XXJ=XXJ+1:IF XXJ>39 THEN 460 GOTO 451 457 XXX$=MID$(XXC$,XXI+5,XXJ-XXI-4) XXY$="XXX$="+XXX$:EVAL XXY$ XXCM$=LEFT$(XXCM$,XXI-1)+XXX$+RIGHT$(XXCM$,LEN(XXC$)-XXJ) IF LEN(XXCM$)>40 THEN 460 RETURN 460 REM LINE TO LONG XXX$="line too long" IF XXCAP=1 THEN XXX$=UCASE$(XXX$) ? XXX$:? "":XXCL$="":XXCR$="":XXCM$="" GOTO 10 1000 REM INIT XXOT=120:XXLT=14:XXTO=XXOT*XXLT:XXEH=0 XXINS=VAL(LEFT$(BIN$(XXSO),1)) XXCAP=VAL(MID$(BIN$(XXSO),2,1)) XXS1=16*INT(SHIFT/16):XXORG$=CWD$ XXCL$="":XXCM$="":XXCR$="":XXOC$="":XXIK$="" GOTO 10