- Installazione
- Obiettivi del progetto
- Estensioni
- Keymaps
- Default keymaps:
- Configurazione
- Localizzazione configurazione
- Extensions API
- Carico dei moduli
- Avviso
- Localizzazione dei plugin
- Componenti decorativi
- Azioni ed effetti
- Il terminale sottostante
- Apipi addizionali
- Tema d’esempio: Hyperyellow
- Estensione di esempio: Hyperpower
Installazione
ultima versione: 3.0.2
64-bit | |
macOS (.app) | 3.0.2 |
Windows (.exe) | 3.0.2 |
Debian (.deb) | 3.0.2 |
Fedora (.rpm) | 3.0.2 |
Altre distro Linux (.AppImage) | 3.0.2 |
Obiettivi del progetto
Lo scopo del progetto è di creare un’esperienza bella ed estensibile per gli utenti dell’interfaccia a riga di comando, costruita su standard web aperti. All’inizio, la nostra attenzione si concentrerà principalmente sulla velocità, la stabilità e lo sviluppo della corretta API per gli autori di estensioni.
In futuro, prevediamo che la comunità proporrà aggiunte innovative per migliorare quella che potrebbe essere l’interfaccia più semplice, potente e ben collaudata per la produttività.
Estensioni
Le estensioni sono disponibili su npm. Incoraggiamo tutti a includere hyper
nel campo keywords
in package.json
.
$ npm search hyper
Poi modifica .hyper.js
e aggiungilo a plugins
module.exports = { config: { /*... */ }, plugins: };
Hyper
mostrerà una notifica quando i tuoi moduli sono installati in .hyper_plugins
.
Keymaps
Tutti i tasti di comando possono essere cambiati. Per cambiarli, modifica .hyper.js
e aggiungi il tuo cambiamento desiderato a keymaps
.
Poi Hyper cambierà il default con il tuo cambiamento personalizzato.
Esempio: 'window:devtools': 'Cmd+Alt+O'
module.exports = { config: { /*... */ }, keymaps: { 'window:devtools': 'cmd+alt+o' }};
Default keymaps:
Configurazione
Localizzazione configurazione
macOS | ~/Library/Application Support/Hyper/.hyper.js |
Windows | $Env:AppData/Hyper/.hyper.js |
Linux | ~/.config/Hyper/.hyper.js |
Nota: la configurazione a ~/.hyper.js
è ancora supportata, ma sarà ignorata, se è presente la configurazione nella directory dell’applicazione. Altrimenti sarà spostata nella directory dell’applicazione alla prima esecuzione.
L’oggetto config
visto sopra in .hyper.js
ammette quanto segue
Property | Default | Description |
updateChannel |
“stabile” | Il canale di aggiornamento da cui ricevere gli aggiornamenti |
fontSize |
12 | La dimensione predefinita in pixel per il terminale |
fontFamily |
“Menlo, DejaVu Sans Mono, Lucida Console, monospace” | La famiglia di font da usare con fallback opzionali |
uiFontFamily |
“-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, …” | La famiglia di caratteri da usare per l’UI con fallback opzionali |
fontWeight |
“normale” | Il peso predefinito del carattere: “normale” o “grassetto” |
fontWeightBold |
“grassetto” | Il peso dei caratteri in grassetto: “normale” o “grassetto” |
cursorColor |
“rgba(248,28,229,0.8)” | Il colore del cursore nel terminale |
cursorAccentColor |
“#000” | Il colore del testo sotto cursore BLOCK |
cursorShape |
“BLOCK” | La forma del cursore nel terminale. Le opzioni disponibili sono: ‘BEAM’, ‘UNDERLINE’, ‘BLOCK’ |
cursorBlink |
“false” | Se vero, il cursore lampeggerà |
foregroundColor |
“#fff” | Il colore del testo principale del terminale |
backgroundColor |
“#000” | Il colore e l’opacità dello sfondo della finestra e del terminale principale |
selectionColor |
“rgba(248,28,229,0.3)” | Il colore/opacità dello sfondo della selezione del testo nel terminale |
borderColor |
“#333” | Il colore del bordo della finestra principale e della barra delle schede |
css |
“” | CSS personalizzato da includere nella finestra principale |
padding |
“12px 14px” | Valori di padding CSS per lo spazio intorno ad ogni termine |
colors |
{ nero: “#000000”, rosso: “#ff0000”, … } | Una lista di sovrascritte per la tavolozza dei colori. I nomi delle chiavi rappresentano gli “ANSI 16”, che possono essere visti tutti nella configurazione predefinita. |
shell |
“” | Un percorso per una shell personalizzata da eseguire quando Hyper inizia una nuova sessione |
shellArgs |
“” | Un array di argomenti della shell |
env |
{} | Un oggetto di variabili d’ambiente da impostare prima lanciare la shell |
windowSize |
La larghezza/altezza predefinita in pixel di una nuova finestra | |
scrollback |
1000 | Il numero di righe da persistere nel buffer del terminale per lo scorrimento |
copyOnSelect |
falso | Se vero, il testo selezionato sarà automaticamente copiato negli appunti |
quickEdit |
falso | Se vero, al clic destro il testo selezionato sarà copiato o incollato se non è presente alcuna selezione (vero di default su Windows) |
defaultSSHApp |
vero | Se vero, Hyper sarà impostato come client di protocollo predefinito per SSH |
modifierKeys |
{altIsMeta: false} | Cambia il comportamento dei tasti modificatori per agire come meta chiave |
showHamburgerMenu |
vero su Linux/Windows, falso su macOS | Cambia la visibilità del menu hamburger. Le opzioni disponibili sono: true, false |
showWindowControls |
“” | Cambia la posizione/visibilità dei controlli della finestra. Le opzioni disponibili sono: true, false, “left” |
Extensions API
Le estensioni sono moduli universali di Node.js caricati sia da Electron che dal processo di rendering.
Il sistema di estensione è progettato intorno alla composizione delle API che usiamo per costruire il terminale: React
componenti e Redux
azioni.
Invece di esporre un metodo o un parametro API personalizzato per ogni possibile punto di personalizzazione, vi permettiamo di intercettare e comporre ogni bit di funzionalità!
L’unica conoscenza che è quindi richiesta per estendere con successo Hyper
è quella delle sue sottostanti librerie open source.
Puoi trovare ulteriori dettagli sullo sviluppo dei plugin nel repository Hyper.
Il tuo modulo deve esporre almeno uno di questi metodi:
Metodo | Invocato da | Descrizione | ||||||
onApp |
Elettro |
Invocato al primo caricamento dell’applicazione. Se un plugin viene ricaricato, viene invocato di nuovo con l’app esistente. Parametri:
|
||||||
onWindow |
Electron |
Invocato quando ogni finestra viene creata. Se un plugin viene ricaricato, viene invocato di nuovo con le finestre esistenti. Parametri:
|
||||||
onUnload |
Electron |
Invocato quando un plugin viene rimosso dall’utente. Parametri:
|
||||||
decorateConfig |
Electron / Renderer |
v0.5.0+. Permette di decorare la configurazione dell’utente. Parametri:
|
||||||
decorateEnv |
Electron |
v0.7.0+. Permette di decorare l’ambiente dell’utente restituendo un oggetto ambiente modificato. Parametri:
|
||||||
decorateMenu |
Electron |
Invocato con il template Parametri:
|
||||||
decorateBrowserOptions |
Electron |
Consente di decorare le opzioni Parametri:
|
||||||
onRendererWindow |
Renderer |
Invocato quando un plugin viene caricato per la prima volta o successivamente ricaricato in ogni finestra. Parametri:
|
||||||
middleware |
Renderer |
Un middleware Redux personalizzato che può intercettare qualsiasi azione. Successivamente invochiamo il |
||||||
reduceUI reduceSessions reduceTermGroups |
Renderer |
Un riduttore personalizzato per lo
|
||||||
getTabsProps |
Renderer |
Passa i props da
|
||||||
getTabProps |
Renderer |
Passa props da
|
||||||
getTermGroupProps |
Renderer |
Passa props da
|
||||||
getTermProps |
Renderer |
Passa props da
|
||||||
mapHyperState mapTermsState mapHeaderState mapNotificationsState |
Renderer |
Un mapper personalizzato per le proprietà di stato che ricevono i componenti contenitore. Notate che per i componenti figli per ottenere queste proprietà, dovete passarle giù usando i metodi corrispondenti (come Deve restituire un oggetto esteso della mappa passata.
|
||||||
mapHyperDispatch mapTermsDispatch mapHeaderDispatch mapNotificationsDispatch |
Renderer |
Un mapper personalizzato per le proprietà dispatch. Deve restituire un oggetto esteso della mappa passata.
|
||||||
decorateHyper decorateNotifications decorateNotification decorateHeader decorateTabs decorateTab decorateTerms decorateTermGroup decorateSplitPane decorateTerm
|
Renderer |
Invocato con il Parametri:
|
Carico dei moduli
L’utente può caricare e ricaricare a caldo i plugin premendo Command + R (refresh). Per favore sforzati di fare plugin che non richiedano un riavvio completo dell’applicazione per funzionare.
Avviso
I plugin che influenzano la `BrowserWindow` avranno effetto sulle nuove finestre dopo l’hot-reload.
In futuro potremmo farlo automaticamente.
Quando sviluppi, puoi aggiungere il tuo plugin a .hyper_plugins/local
e poi specificarlo sotto l’array localPlugins
in .hyper.js
. Carichiamo nuovi plugin:
- Periodicamente (ogni poche ore)
- Quando vengono apportate modifiche al file di configurazione (
plugins
olocalPlugins
) - Quando l’utente clicca su Plugins > Update all now
Il processo di ricarica comporta
- L’esecuzione di
npm prune
enpm install
in.hyper_plugins
. - Eseguire il
require.cache
sia nell’elettrone che nel processo di rendering - Invocando i metodi
on*
sulle istanze esistenti e renderizzando nuovamente i componenti con le decorazioni fresche al loro posto.
Localizzazione dei plugin
macOS | ~/Library/Application Support/Hyper/.hyper_plugins |
Windows | $Env:AppData/Hyper/.hyper_plugins |
Linux | ~/.config/Hyper/.hyper_plugins |
Nota: i plugin a ~/.hyper_plugins
sono ancora supportati, ma saranno ignorati, se sono presenti plugin nella directory dell’applicazione. Altrimenti saranno spostati nella directory dell’applicazione alla prima esecuzione.
Nota: sul processo principale, i plugin sono registrati appena possibile (spariamo onLoad
). Sul browser, sta all’utente innescare il loro caricamento premendo command+R. Mettiamo l’utente in controllo del caricamento in questo modo per evitare che perda lavoro critico a causa di estensioni che azzerano lo stato o non lo conservano correttamente.
Componenti decorativi
Diamo la possibilità di fornire un componente di ordine superiore per ogni pezzo dell’Hyper
UI.
La sua struttura è la seguente:
<Hyper> <Header> <Tabs> <Tab /> ... </Tabs> </Header> <Terms> <TermGroup> <SplitPane> <TermGroup> <Term /> ... </TermGroup> <TermGroup> <Term /> ... </TermGroup> </SplitPane> </TermGroup> </Terms> <Notifications> <Notification /> ... </Notifications></Hyper>
Tutti i metodi decorate*
ricevono i seguenti riferimenti in un oggetto passato come secondo parametro:
React |
L’intero namespace React. |
notify |
Una funzione helper che mostra una notifica sul desktop. Il primo parametro è il titolo, il secondo è il corpo opzionale della notifica, e il terzo è un altro parametro opzionale che può essere usato per registrare i dettagli nella console di sviluppo. Per passare questi dettagli, è sufficiente fornire un oggetto con una proprietà |
Notification |
Il componente Notification in caso si voglia riutilizzare. |
Tutti i componenti accettano le seguenti due proprietà per estendere il loro markup:
customChildren |
Un array di Element o un singoloElement da inserire in fondo al componente. |
customChildrenBefore |
Lo stesso della proprietà precedente, ma inserito come primo elemento figlio(i) del componente. |
Il componente di ordine superiore può fornire una onDecorated
proprietà al componente decorato per ottenere un riferimento alla sua istanza.
Il tuo componente di ordine superiore Term può fornire una proprietà onCursorMove
handler che viene chiamata quando il cursore si è spostato con un parametro oggetto che rappresenta la sua posizione relativa all’origine Term:
x |
Posizione orizzontale in pixel |
y |
Posizione verticale in pixel |
width |
Larghezza cursore in pixel |
height Altezza del cursore in pixel |
|
col |
Posizione orizzontale in colonne |
row |
Posizione verticale in righe |
Vi invitiamo a mantenere la compatibilità con altri decoratori. Poiché molti possono essere impostati, non dare per scontato che il tuo sia l’unico.
Per esempio, se stai passando dei bambini, componi potenziali valori esistenti:
render () { const customChildren = Array.from(this.props.customChildren) .concat(<p>My new child</p>); return <Tab {...this.props} customChildren={customChildren} />}
O se usi onDecorated
proprietà
onDecorated (term) { this.term = term; if (this.props.onDecorated) { this.props.onDecorated(term); }}
Azioni ed effetti
Tutte le azioni di Redux sono disponibili per te da gestire attraverso i tuoi middleware e riduttori. Per un esempio, fate riferimento al plugin di riferimento di Hyperpower.
Gli effetti collaterali si presentano in due forme fondamentali:
- Alcune azioni inviano altre azioni in base allo stato.
- Alcune azioni fanno un lavoro asincrono comunicando sul canale RPC al processo principale
In tutti i casi, l’effetto collaterale viene passato come chiave effect
nell’azione e poi gestito dal nostro middleware.
Questo significa che puoi sovrascrivere, comporre o eliminare completamente gli effetti! In altre parole, questo è il modo in cui puoi cambiare la funzionalità o il comportamento predefinito dell’app.
Come esempio, considera l’azione che usiamo per aumentare la dimensione del carattere quando premi Command+=
:
export function increaseFontSize () { return (dispatch, getState) => { dispatch({ type: UI_FONT_SIZE_INCR, effect () { const state = getState(); const old = state.ui.fontSizeOverride || state.ui.fontSize; const value = old + 1; dispatch({ type: UI_FONT_SIZE_SET, value }); } }); };}
Il terminale sottostante
Hyper
raggiunge molta della sua velocità e funzionalità grazie alla potenza di xterm.js
Apipi addizionali
Gli oggetti Electron app
sono estesi con le seguenti proprietà:
config |
Un Object con il blocco config da .hyper.js . |
plugins |
Un Object con helper per i plugin. |
getWindows |
Un Function che restituisce un Set di tutte le finestre aperte. |
createWindow |
Un Function che crea una nuova finestra. Accetta un callback opzionale che sarà passato come init callback della nuova finestra. |
Gli oggetti Electron BrowserWindow
sono estesi con i seguenti parametri:
rpc |
Un EventEmitter che permette la comunicazione con il processo window. |
sessions |
Un Map di Session oggetti che tengono la comunicazione con ogni pty. |
Le finestre di rendering sono similmente estese con:
rpc |
Un EventEmitter che permette la comunicazione con il processo della finestra. |
store |
L’oggetto Redux Store . Questo permette di accedere alle azioni dispatch o di leggere lo stato globale con getState . |
L’oggetto rpc
è simmetrico tra browser e processo di rendering. L’API è la stessa di Node.js, con l’eccezione che ammette un solo oggetto come unico parametro:
window.rpc.emit('hi there', { some: 'payload', any: });
Tema d’esempio: Hyperyellow
La seguente estensione altera semplicemente la configurazione per aggiungere CSS e colori gialli! Ecco il codice.
I temi sono semplicemente dei plugin! Solo un hook, decorateConfig
è necessario:
exports.decorateConfig = (config) => { return Object.assign({}, config, { borderColor: 'yellow', cursorColor: 'yellow', css: ` ${config.css || ''} .tabs_nav .tabs_list .tab_text { color: yellow; } .tabs_nav .tabs_title { color: yellow; } ` });}
Ho afferrato i nomi delle classi ispezionando il termine con Devtools, che puoi attivare da View -> Toggle Developer Tools
. Quando lo fai, nota che alcune classi sono generate automaticamente e seguite da un nonce casuale (ad esempio: term_13hv8io
). Ignoratele: cambiano con ogni nuova finestra!
Nota l’enfasi sul giocare bene con le altre estensioni. In particolare, creiamo un nuovo oggetto, estendiamo solo le chiavi che ci interessano e componiamo il CSS per preservare l’impostazione dell’utente e quella degli altri autori:
return Object.assign({}, config, { css: ` ${config.css || ''} /* your css here */ `});
Estensione di esempio: Hyperpower
La seguente estensione rende le particelle mentre il cursore si muove:
Passiamo attraverso il suo codice.
Prima, intercettiamo l’azione Redux SESSION_ADD_DATA
. Potete trovare l’elenco completo delle azioni nel repository.
exports.middleware = (store) => (next) => (action) => { if ('SESSION_ADD_DATA' === action.type) { const { data } = action; if (/bash: wow: command not found/.test(data)) { store.dispatch({ type: 'WOW_MODE_TOGGLE' }); } else { next(action); } } else { next(action); }};
Nota che non re-dispatchiamo l’azione, il che significa che non rendiamo mai l’output del comando al terminale. Invece, inviamo una nostra azione, che prendiamo nel uiReducer
e successivamente mappiamo:
exports.reduceUI = (state, action) => { switch (action.type) { case 'WOW_MODE_TOGGLE': return state.set('wowMode', !state.wowMode); } return state;};exports.mapTermsState = (state, map) => { return Object.assign(map, { wowMode: state.ui.wowMode });};
Vogliamo poi decorare il componente <Term>
in modo da poter accedere al caret sottostante.
Tuttavia, <Term>
non è un contenitore su cui possiamo mappare i puntelli. Così usiamo getTermProps
per passare la proprietà più in basso:
exports.getTermProps = (uid, parentProps, props) => { return Object.assign(props, { wowMode: parentProps.wowMode });}
L’estensione restituisce quindi un componente di ordine superiore per avvolgere <Term>
. Notate che passiamo la proprietà onDecorated
per accedere al componente Term base e al suo DOM ref, e la proprietà onCursorMove
per usare l’API Hyper cursor:
render () { return React.createElement(Term, Object.assign({}, this.props, { onDecorated: this._onDecorated, onCursorMove: this._onCursorMove }));}