Premessa
Questo tutorial è estratto dall’approfondimento del capitolo 4.1 del mio libro “Il Nuovo Java”.
È possibile scaricare gratuitamente tale approfondimento insieme a tanto altro materiale (circa 1000 pagine) dell’espansione online del libro “Il Nuovo Java” all’indirizzo https://www.nuovojava.it.
1.1 JShell
Una delle novità più interessanti che ha portato con sé Java 9, non riguarda il linguaggio, ma il JDK. Infatti è stata aggiunta alla suite di applicazioni storiche come java, javadoc, javac, etc., la console JShell. Si tratta di un software della tipologia REPL, acronimo di Read-Evaluate-Print Loop, che possiamo tradurre come ciclo leggi-valuta-stampa. Infatti un software REPL è implementato di solito come una console interattiva, che quando attivata apre un loop (ciclo) con cui si mette in attesa di input da parte dell’utente. Ad ogni input che viene confermato dall’utente il software lo legge, lo valuta e stampa un risultato. Ma a cosa serve JShell?
Per testare come funziona una certa parte di codice, solitamente dobbiamo scrivere un programma intero, che come minimo richiede l’esecuzione di una classe che contiene il metodo main
(ma di solito anche la compilazione). Poi bisogna risolvere eventuali errori ripetendo il ciclo scrivi(-compila)-esegui-valuta, tante volte fino a quando non risolveremo ogni problema.
Con JShell è possibile scrivere vari tipi di snippet come statement, espressioni, metodi, variabili, classi, import e così via, senza dover obbligatoriamente scrivere le espressioni nei metodi, o i metodi nelle classi o scrivere un metodo main
. Non è nemmeno necessario compilare: ogni input passato a JShell viene immediatamente letto e valutato, quindi viene stampato un messaggio di risposta sulla valutazione. Non ci sarà neanche bisogno di usare obbligatoriamente i comandi di stampa come abbiamo fatto sinora. JShell ci permetterà di risparmiare tempo e ci invoglierà a sperimentare più facilmente il nostro codice, a creare prototipi, scoprire le librerie standard come funzionano davvero ed altro ancora. Può quindi accelerare il processo di apprendimento.
JShell non sostituisce un IDE, ma è possibile copiare il codice da un IDE e incollarlo in JShell per semplificarne il test. Naturalmente è possibile anche copiare il codice da JShell per incollarlo all’interno di un IDE.
Nel momento in cui stiamo scrivendo, abbiamo verificato che le versioni di Java successive alla 11 (comprese la 17) JShell non riconoscono la pressione di alcune combinazioni di tasti, come quelle che usiamo di scrivere le parentesi graffe. Per tale ragione, per gli esempi di questo tutorial abbiamo usato la versione del JDK 11.
1.1.1 HelloWorld con JShell
Per aprire una sessione con JShell, è necessario semplicemente aprire una prompt dei comandi (programma cmd
), e da lì eseguire il comando:
jshell
(è possibile anche eseguire direttamente il comando jshell
dal menu Start
di Windows, senza aprire prima la prompt dei comandi).
JShell ci darà il benvenuto e ci inviterà ad eseguire un comando per ottenere ulteriori informazioni. Digitando quindi il comando suggerito:
/help intro
JShell ci descriverà come funziona in breve, mostrando anche qualche semplice esempio, come è possibile osservare nella figura 1.
Figura 1 – Apertura sessione JShell ed esecuzione comando “/help intro”.
Nel messaggio di introduzione viene subito fatta una distinzione tra i comandi di JShell (per esempio /help intro
) e i cosiddetti snippet (ovvero i frammenti di codice Java che JShell legge, valuta e stampa). I comandi JShell iniziano tutti con il simbolo /
, e possiamo leggerne la lista completa digitando semplicemente il comando:
/help
oppure più brevemente:
/?
Invece possiamo scrivere qualsiasi istruzione Java all’interno di una sessione JShell e lasciarla processare premendo il tasto Enter
(Invio
). Per esempio possiamo stampare al volo la stringa Hello World!
nel seguente modo:
jshell> System.out.println("Hello World!")
ed ottenere la risposta:
Hello World!
Si noti che non c’è stato neanche bisogno di utilizzare il “;” finale, che in Java caratterizza tutti gli statement. Questo perché JShell, come vedremo nel prossimo paragrafo, ha regole meno restrittive rispetto al classico compilatore Java.
Se digitassimo il nostro codice scorrettamente:
jshell> System.out.PRINTLN("Hello World!")
otterremo un errore da JShell:
| Error: | cannot find symbol | symbol: method PRINTLN(java.lang.String) | System.out.PRINTLN("Hello World!") | ^----------------^
Per uscire da una sessione JShell (ed essere salutati), basta digitare il comando:
jshell> /exit | Goodbye
1.1.2 JShell e codice Java
Abbiamo visto che all’interno di una sessione JShell è possibile alternare codice Java (snippet, classi, metodi, e così via) e comandi JShell. Per quanto riguarda il codice Java, JShell si pone l’obiettivo di rappresentare uno strumento per testarlo nel modo più veloce possibile. Come abbiamo già notato non occorre creare per forza classi, metodi e seguire tutte le classiche regole di Java, bensì tale strumento cerca di facilitare la codifica e quindi ci sono alcune regole un po’ diverse rispetto a quelle classiche. Partiamo subito con degli esempi.
Consigliamo al lettore di scrivere le istruzioni seguenti passo dopo passo per familiarizzare con JShell. Tra un esempio e l’altro potrà anche testare altre istruzioni. Si può anche tranquillamente lavorare con due sessioni JShell separate.
1.1.2.1 Esempi pratici
La prima regola che cambia l’abbiamo già notata: con le espressioni su di un’unica riga non c’è bisogno di utilizzare il “;
” finale. Possiamo quindi dichiarare una variabile intera uno
, inizializzata con il valore 1
nel seguente modo:
jshell> int uno = 1 uno ==> 1
Si noti come JShell abbia restituito la valutazione dello snippet stampando a video:
uno ==> 1
che va interpretato come “la variabile uno
vale 1”. Ora dichiariamo una variabile booleana senza inizializzarla:
jshell> boolean b b ==> false
In questo caso la variabile booleana b è automaticamente inizializzata al suo valore di default false
(come una variabile d’istanza quando viene istanziato un oggetto). Possiamo quindi già notare la seconda regola differente rispetto al compilatore Java, che riguarda l’inizializzazione delle variabili. Le variabili degli snippet non inizializzate sono automaticamente impostate ai propri valori nulli, come se fossero variabili d’istanza. Se proviamo a dichiarare un’altra variabile con lo stesso nome della precedente (b
) nel seguente modo:
jshell> boolean b b ==> false
JShell non avrà problemi ad utilizzarla. Infatti la nuova dichiarazione della variabile b
va a sovrascrivere la precedente dichiarazione. All’interno di codice Java ordinario, questa situazione avrebbe provocato un errore in compilazione, perché non si possono dichiarare due variabili con lo stesso nome. Quindi ecco una terza regola differente per JShell rispetto al compilatore Java: dichiarare due volte la stessa variabile (o lo stesso metodo) causa la sovrascrittura della prima variabile dichiarata (o del primo metodo dichiarato). Nella programmazione standard questa situazione provocherebbe un errore in compilazione. Anche in questo caso non avendo fornito un’inizializzazione alla variabile b
, viene assegnato automaticamente il valore nullo per il tipo di dato, che per un tipo byte
equivale a 0
. Assegniamo poi il valore 128
alla variabile b
. Ricordiamo che il valore massimo che può assumere un tipo di dato byte
è 127
, quindi otterremo un errore:
jshell> b = 128 | Error: | incompatible types: possible lossy conversion from int to byte | b = 128 | ^-^
I messaggi di JShell seguono sempre un simbolo di “|” (in inglese si legge “pipe”).
Quindi forziamo l’assegnazione con un cast a byte
:
jshell> b = (byte)128 b ==> -128
Come spiegato nel capitolo 3, il valore 128
immagazzinato nella variabile byte b
, diventa -128
. A causa del troncamento dei primi 24 bit della rappresentazione binaria di 128
. Proviamo quindi a sottrarre un’unità al numero che doveva essere 128
e che invece risulta essere rappresentato in un byte come -128
, e assegniamolo nuovamente alla variabile b
. Anche in questo caso bisogna ricorrere al cast visto che un’espressione tra un tipo byte
e un tipo int
(la sottrazione b-uno
) restituisce un risultato di tipo intero:
jshell> b = (byte)(b-uno) b ==> 127
Il valore è ora correttamente immagazzinato nella variabile byte
. Adesso eseguiamo il comando di stampa sommando b
e di nuovo la variabile uno
:
jshell> System.out.print(b+uno) 128
Questa volta viene stampato il valore corretto, visto che b+uno
, è un’espressione tra un byte
ed un int
, e quindi il risultato viene promosso ad int
, e 128
è un valore rappresentabile come tipo int
.
Notare che abbiamo invocato il metodo
System.out
, invece del più usato metodoprintln
. La differenza risiede nel fatto cheprintln
stampa il valore in input e poi va a capo (“println” è l’abbreviativo di “print line”). Nel nostro esempio era inutile andare a capo e quindi ne abbiamo approfittato per introdurre il metodo
Possiamo anche definire classi, enumerazioni, annotazioni ed anche metodi isolati, che probabilmente non sarà possibile scrivere su di un’unica riga come gli snippet scritti sinora. Ogni volta che andiamo a capo JShell, a meno di errori di sintassi, non valuterà quanto abbiamo scritto, ma aspetterà il completamento della struttura dati che stiamo definendo. Dobbiamo tener conto che per i tipi Java (classi, interfacce, record, enumerazioni ed annotazioni) non innestati saranno ignorati tutti i modificatori (tranne abstract
), e che non è possibile dichiarare package o moduli. Infine, se chiamiamo un metodo che non abbiamo ancora definito, JShell ci avvertirà con un warning, ma ci consentirà di andare avanti considerando valido il nostro codice.
1.1.2.2 Sommario delle regole di JShell
Scrivere codice in JShell, presenta quindi alcune differenze rispetto a scriverlo all’interno di classi Java. Queste differenze hanno lo scopo di semplificare l’esperienza di codifica, ma contemporaneamente pongono anche dei limiti alla programmazione. Riassumiamo di seguito le principali differenze.
- Benché sia possibile dichiarare metodi, non è richiesto obbligatoriamente dichiararne uno per scrivere uno statement.
- Benché sia possibile dichiarare classi, non è richiesto obbligatoriamente dichiararne una per scrivere metodi o variabili.
- Se scriviamo statement in un’unica linea, non è necessario utilizzare il simbolo “
;
”. - Non è possibile dichiarare package (cfr. capitolo 5) o moduli (cfr. capitolo 16).
- Per tutti i tipi non innestati (cfr. modulo 13), tutti i modificatori fondamentali, a parte
abstract
(cfr. capitolo 6), sono ignorati o non permessi da JShell. - La parola chiave
synchronized
(cfr. capitolo 12) è sempre ignorata. - Dichiarare due volte la stessa variabile (o lo stesso metodo) causa la sovrascrittura della prima variabile dichiarata (o del primo metodo dichiarato); nella programmazione standard questa situazione provocherebbe un errore in compilazione.
- Dichiarare in uno snippet una variabile senza inizializzarla, implica che essa sia automaticamente inizializzata al proprio valore nullo.
1.1.3 Comandi JShell
I comandi JShell si distinguono dal codice Java perché sono sempre preceduti dal prefisso /
. Sino ad ora abbiamo eseguito solo due comandi: il comando /help
(equivalente a /?
) ed il comando /exit
. Cerchiamo di fare una breve panoramica dei comandi principali di JShell.
1.1.3.1 Comandi esplorativi
Proviamo ad eseguire il comando /history:
jshell> /history int uno = 1 boolean b byte b b = 128 b = (byte)128 b = (byte)(b-uno) System.out.print(b+uno) /history
Questo comando ci mostra la storia di tutto quello che abbiamo digitato in questa sessione (sia snippet che comandi JShell). Se invece siamo interessati solo agli snippet possiamo utilizzare il comando
/list:
jshell> /list 1 : int uno = 1; 3 : byte b; 4 : b = (byte)128 5 : b = (byte)(b-uno) 6 : System.out.println(b+uno)
Viene mostrato un elenco numerato degli snippet validi che abbiamo eseguito. Ogni snippet ha il suo snippet id (numero identificatore). Come si può notare manca lo snippet id 2, dove avevamo dichiarato b
come variabile booleana, ma che poi abbiamo sovrascritto con la definizione di b
come variabile byte
(snippet id 3). Non è stato riportato neanche lo snippet che ha provocato un errore. Notiamo inoltre come solo per gli snippet id 1 e 3 sia stato aggiunto il simbolo “;
”. Questo perché JShell evidenzia il “;
” solo quando si tratta di una dichiarazione. Gli snippet id possono essere richiamati con la sintassi:
/snippetId
Se richiamassimo uno snippet id relativo ad una dichiarazione di una variabile, essa verrà ridichiarata sovrascrivendo il valore che aveva assunto precedentemente. Il comando
/help
eseguito senza aggiungere opzioni elenca tutti i possibili comandi che possiamo eseguire con una breve spiegazione. È possibile invece avere qualche dettaglio in più su come funzionano i vari comandi facendo seguire al comando /help il nome del comando JShell di cui si desiderano le informazioni. In generale quindi possiamo digitare:
/help nomeComando
Per esempio:
jshell> /help /list | | /list | | Show the source of snippets, prefaced with the snippet id. | | /list | List the currently active snippets of code that you typed or read with /open | | /list -start | List the automatically evaluated start-up snippets | | /list -all | List all snippets including failed, overwritten, dropped, and start-up | | /list <name> | List snippets with the specified name (preference for active snippets) | | /list <id> | List the snippet with the specified snippet id
Scopriamo così che è possibile passare delle opzioni al comando /list. In particolare per vedere tutti i dettagli della nostra sessione, compresi gli snippet non validi e le istruzioni che ha implicitamente aggiunto JShell, possiamo eseguire il comando /list -all
:
jshell> /list -all s1 : import java.io.*; s2 : import java.math.*; s3 : import java.net.*; s4 : import java.nio.file.*; s5 : import java.util.*; s6 : import java.util.concurrent.*; s7 : import java.util.function.*; s8 : import java.util.prefs.*; s9 : import java.util.regex.*; s10 : import java.util.stream.*; 1 : int uno = 1; 2 : boolean b; 3 : byte b; e1 : b = 128 4 : b = (byte)128 5 : b = (byte)(b-uno) 6 : System.out.println(b+uno)
Da questo output possiamo capire varie cose. Per esempio che JShell importa alcune librerie automaticamente per semplificarci la vita. Infatti esiste uno script di startup che importa automaticamente le librerie listate nell’esempio precedente e che viene eseguito quando parte la sessione di JShell. Le librerie sono identificate con un id composto dalla lettera “s” (iniziale di “start”) e un numero sequenziale, ovvero s1
, s2
, s3
, etc. Vedremo nel paragrafo successivo come sia possibile cambiare queste impostazioni. Se vogliamo vedere solo i package importati possiamo usare il comando:
jshell> /list -start
oppure il comando
/imports:
jshell> /imports
che non ci mostrerà la numerazione s1
, s2
, s3
, etc. accanto ad ogni istruzione di import
. La differenza tra i due comandi risiede soprattutto nel fatto che quest’ultimo riporterà anche altre eventuali istruzioni di import
digitate come snippet, mentre il primo riporterà solo gli import
inclusi di default.
Possiamo anche notare che in questo output è presente anche lo snippet con id 2, anche se è stato sovrascritto dallo snippet con id 3. Inoltre viene listata anche l’istruzione (b = 128
) che ha causato l’errore, a cui stato assegnato lo snippet id e1
(la lettera “e” sta per “error”). I comandi /types
, /vars
e /methods
, hanno la stessa funzione di /list
, ovvero quella di elencare quanto già digitato. La differenza è che il comando /types
mostra solo i tipi dichiarati (classi interfacce, annotazioni, record ed enumerazioni), il comando /methods
mostra solo i metodi dichiarati (non quelli dichiarati nelle classi), il comando /vars
mostra solo le variabili dichiarate (non quelle dichiarate nelle classi e nei metodi). Questi comandi condividono le stesse opzioni del comando /list
: per esempio -all
per vedere tutte le occorrenze valide e non valide (di tipi, variabili, metodi), -start
per vedere cosa appartiene allo script di partenza della sessione (di tipi, variabili, metodi), oppure è possibile specificare lo snippet id o il nome (di tipi, variabili, metodi).
1.1.3.2 Comandi esecutivi
Abbiamo già asserito che esiste uno script di startup che importa automaticamente alcuni package, e che esso viene eseguito quando parte la sessione di JShell. In particolare abbiamo visto che di default JShell esegue uno script che importa i più comuni package (vedi esempio precedente).
Tale lista di import
può essere configurata mediante il comando /set start
; sono già disponibili tre configurazioni diverse, ma è anche possibile crearne di nuove. Oltre alla configurazione di default (che si chiama appunto DEFAULT
), esistono altre due configurazioni predefinite: JAVASE
e PRINTING
. Con il comando:
jshell> /set start -retain PRINTING
otterremo che sarà impostato come script di startup per le prossime sessioni lo script PRINTING
.
Se non specifichiamo l’opzione
-retain
, lo script di startup non sarà mantenuto per le prossime sessioni.
Se vogliamo applicare lo script impostato nella sessione corrente da subito, dobbiamo eseguire il comando /reload
, che rilancia anche tutte le istruzioni valide eseguite nella sessione. Lo script PRINTING
metterà a disposizione dei metodi con nomi brevi per la stampa, e potremo usare in luogo di System.out.println
, System.out.print
e System.out.printf
, rispettivamente i metodi println
, print
e printf
.
Il terzo script JAVASE
invece importa tutti i package possibili di Java Standard Edition. In questo modo non saremo obbligati a importare mai nulla, ma dovremo aspettare qualche secondo in più prima che parta JShell. È possibile anche impostare più di uno script di startup alla volta, per esempio:
jshell> /set start -retain DEFAULT PRINTING
Per impostare script personalizzati invece, possiamo scrivere:
jshell> /set start -retain C:/MiaCartella/MioScript
Oppure andare a scrivere in un file l’attuale configurazione di startup con il comando
/save:
jshell> /save -start C:/MiaCartella/MioScript
Con il comando /save
possiamo anche salvare in un file altre informazioni. Per esempio possiamo salvare tutta la lista delle istruzioni valide che abbiamo digitato con:
jshell> /save C:/MiaCartella/MioScript
oppure tutta la lista delle istruzioni valide e non valide:
jshell> /save -all C:/MiaCartella/MioScript
oppure tutta la history della sessione corrente:
jshell> /save -history C:/MiaCartella/MioScript
Con il comando
/open invece, possiamo aprire un file precedentemente salvato. Si può trattare anche di un file .java
. Per esempio:
jshell> /open C:/MiaCartella/HelloWorld.java
Con
/env possiamo impostare la variabile CLASSPATH
per farla puntare a qualche libreria (file .jar
), con la sintassi:
jshell> /env –class-path C:/MiaCartella/MiaLibreria.jar
I concetti di CLASSPATH (introdotto nel primo capitolo) e file JAR, sono presentati all’interno dell’appendice E.
Con /env
è possibile anche impostare il cosiddetto MODULEPATH
, che però sarà argomento dell’ultimo modulo di questo libro.
Il comando
/drop può eliminare uno snippet, specificando il suo nome o il suo id.
Con il comando
/reset invece, il comando /list
sarà ripulito di tutte le istruzioni eseguite. Il comando /history
invece continuerà a funzionare come funzionava precedentemente l’esecuzione del comando /reset
.
È possibile richiamare l’ultima riga (valida o non valida) editata anche con il comando
/!.
1.1.4 Strumenti ausiliari di JShell
Siccome JShell viene eseguito all’interno di una prompt DOS, è possibile sfruttarne alcune comodità. Per esempio possiamo richiamare precedenti righe digitate anche usando il tasto di Freccia Su ↑
(e tornare indietro con il tasto Freccia Giù ↓
). È possibile anche copiare, incollare e ricercare mediante le funzionalità della prompt DOS, come descritto nell’appendice C.
Ma questi non sono gli unici aiuti di cui si può usufruire utilizzando JShell.
1.1.4.1 Variabili implicite
JShell assegna un reference o una variabile primitiva implicitamente, nel caso non ne assegniamo noi una esplicitamente, deducendone il tipo automaticamente. Si parla di variabili implicite con tipo dedotto (implicit variables with type inferred). Per esempio, se scriviamo:
jshell> 1 $1 ==> 1
possiamo notare che a 1 viene assegnata implicitamente la variabile intera $1
(il tipo dedotto automaticamente). Possiamo richiamare la variabile ed utilizzarla, per esempio:
jshell> $1 + $1 $2 ==> 2
si noti come sia stata creata anche una seconda variabile implicita ($2
).
1.1.4.2 Forwarding reference
Abbiamo già asserito che possiamo dichiarare anche tipi o metodi, e che magari possiamo anche copiarli in JShell a partire da codice già scritto. In casi come questi potrebbe capitare di invocare metodi, o utilizzare classi, non ancora definiti. Per esempio, se dichiarassimo un reference di una classe non ancora dichiarata:
jshell> Utente u; | created variable u, however, it cannot be referenced until class Utente is declared
JShell la creerebbe, ma ci avvertirebbe che non sarà possibile utilizzarla fin quando la classe Utente non sarà dichiarata. Se creassimo la classe Utente successivamente:
jshell> class Utente {} | created class Utente | update replaced variable u, reset to null
la variabile u sarebbe inizializzata al suo valore di default (null
). Un discorso simile si ripete se proviamo a chiamare un metodo non ancora definito:
jshell> void testForward() { ...> stampa(); ...> } | created method testForward(), however, it cannot be invoked until method stampa() is declared
1.1.4.3 Auto-completamento
Il tasto TAB
, può essere utilizzato per l’auto-completamento, sia per snippet che per comandi JShell. Per esempio, se dopo aver scritto Strin
battiamo il tasto TAB
, otterremo il seguente output:
jshell> Strin String StringBuffer StringBufferInputStream StringBuilder StringIndexOutOfBoundsException StringJoiner StringReader StringTokenizer StringWriter jshell> String
Quindi ci vengono proposte tutte le possibili opzioni per completare il nostro codice, ma intanto viene scelto quello più probabile. TAB
può essere usato ogni volta che si vuole un aiuto o che si vuole esplorare una particolare classe, libreria o metodo, e anche un comando JShell. Con una doppia pressione del tasto TAB
si ottiene la documentazione ufficiale dell’ultima dichiarazione, da scorrere pagina dopo pagina sempre con il tasto TAB
.
Un altro ausilio per completare automaticamente il nostro codice, JShell ce lo offre con un’insolita combinazione di tasti. Per importare automaticamente una classe non ancora importata per esempio, bisogna prima utilizzare tale classe. Poi premere contemporaneamente i tasti SHIFT
e TAB
, rilasciarli e dopo premere il tasto i (che sta per “import”). Per esempio, se utilizziamo questa combinazione di tasti dopo aver digitato:
jshell> new JButton
allora JShell ci proporrà di scegliere tra gli import possibili o di non fare niente (opzione 0
):
0: Do nothing 1: import: javax.swing.JButton Choice: Imported: javax.swing.JButton
Oppure, se dopo aver dichiarato un valore, vogliamo dichiarare un reference (o una variabile primitiva) basterà semplicemente premere contemporaneamente i tasti SHIFT
e TAB
, rilasciarli, quindi premere il tasto v
(che sta per “variable”). JShell dedurrà il tipo della variabile, la dichiarerà e posizionerà il cursore subito dopo per permetterci di definire il reference. Infatti dopo aver istanziato un Integer
, utilizzando la suddetta combinazione di tasti otteniamo:
jshell> new Integer(1); jshell> Integer = new Integer(1);
dove il cursore è posizionato prima del simbolo =
. Non ci resta che scrivere il nome del reference e confermare:
jshell> Integer intero = new Integer(1); intero ==> 1
1.1.4.4 Il comando /edit
Il comando
/edit apre un semplice editor chiamato JShell Edit Pad (vedi figura 2), che in alcuni casi (come nei copia-incolla) semplifica lo sviluppo del codice.
Figura 2 – JShell Edit Pad in azione.
Tutto quello che scriveremo in JShell Edit Pad, può essere riportato al volo su JShell facendo clic sul bottone Accept
(JShell si aggiornerà contestualmente con i nuovi valori editati), oppure sarà riportato automaticamente dopo che si è chiuso JShell Edit Pad facendo clic sul bottone Exit
.
Cancellare istruzioni già presenti non significa eliminarle come se si stesse usando il comando
/drop
. Semplicemente non le vedremo nell’editor.
Le modifiche saranno ignorate se facciamo clic su Cancel.
Se vogliamo sfruttare un altro editor più completo (per esempio Notepad++) è possibile impostarlo come default per la sessione corrente (per l’impostazione permanente utilizzare l’opzione -retain) con il comando /set:
jshell> /set editor C:\Program Files (x86)\Notepad++\notepad++.exe | Editor set to: C:\Program Files (x86)\Notepad++\notepad++.exe
Salvando il file in Notepad++, otterremo lo stesso effetto del bottone Accept
di JShell Edit Pad. Con il comando
/set è possibile anche configurare altre funzionalità. Per esempio, con l’opzione
feedback, è possibile aumentare la verbosità dei messaggi di analisi specificando il valore
verbose (saranno descritte testualmente le operazioni eseguite), oppure diminuirla specificando il valore
coincise (saranno stampati solo i risultati delle operazioni e non delle dichiarazioni), o evitarli del tutto con il comando
silent. Per i più esigenti esistono anche le opzioni,
mode,
format,
prompt e
truncation, per personalizzare ulteriormente JShell. Si rimanda alla documentazione (comando /help
) se si è interessati a questi dettagli.
1.1.4.5 Scorciatoie da tastiera (shortcuts)
JShell offre alcune scorciatoie da tastiera, in inglese shortcuts (ovvero combinazioni di tasti) per automatizzare dei comandi predefiniti. Segue una tabella esplicativa dei comandi disponibili (i tasti vanno premuti contemporaneamente):
Shortcut | Descrizione |
CTRL a |
Sposta il cursore all’inizio della riga |
CTRL e |
Sposta il cursore alla fine della riga |
ALT b |
Sposta il cursore un carattere indietro |
ALT f |
Sposta il cursore un carattere avanti |
CTRL b |
Sposta il cursore all’inizio della parola precedente |
CTRL f |
Sposta il cursore all’inizio della parola successiva |
CTRL r |
Esegue una ricerca dell’ultimo comando o snippet che contiene i caratteri digitati subito dopo CTRL r |
CTRL t |
Scambia i due caratteri alla sinistra del cursore |
CTRL w |
Cancella la parola alla sinistra del cursore |
ALT d |
Cancella la parola alla destra del cursore |
CTRL k |
Cancella tutto quanto è alla destra del cursore fino alla fine della riga |
CTRL u |
Cancella tutto quanto è alla sinistra del cursore fino alla fine della riga |