- Installation
- Buts du projet
- Extensions
- Keymaps
- Maps de touches par défaut :
- Configuration
- L’emplacement de la configuration
- Extensions API
- Chargement de modules
- Notice
- L’emplacement des plugins
- Décoration des composants
- Actions et effets
- Le terminal sous-jacent
- Autres API
- Exemple de thème : Hyperyellow
- Exemple d’extension : Hyperpower
Installation
dernière version : 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 |
Autres distros Linux (.AppImage) | 3.0.2 |
Buts du projet
Le but du projet est de créer une expérience belle et extensible pour les utilisateurs de l’interface de ligne de commande, construite sur des standards web ouverts. Au début, nous nous concentrerons principalement autour de la vitesse, de la stabilité et du développement de l’API correcte pour les auteurs d’extensions.
À l’avenir, nous prévoyons que la communauté proposera des ajouts innovants pour améliorer ce qui pourrait être l’interface la plus simple, la plus puissante et la mieux testée pour la productivité.
Extensions
Les extensions sont disponibles sur npm. Nous encourageons tout le monde à inclure hyper
dans le keywords
champ package.json
.
$ npm search hyper
Puis éditer .hyper.js
et l’ajouter à plugins
module.exports = { config: { /*... */ }, plugins: };
Hyper
montrera une notification lorsque vos modules seront installés à .hyper_plugins
.
Keymaps
Toutes les clés de commande peuvent être modifiées. Afin de les changer, éditez .hyper.js
et ajoutez votre changement désiré à keymaps
.
Puis Hyper changera le défaut avec votre changement personnalisé.
Exemple : 'window:devtools': 'Cmd+Alt+O'
module.exports = { config: { /*... */ }, keymaps: { 'window:devtools': 'cmd+alt+o' }};
Maps de touches par défaut :
Configuration
L’emplacement de la configuration
macOS | ~/Library/Application Support/Hyper/.hyper.js |
Windows | $Env:AppData/Hyper/.hyper.js |
Linux | ~/.config/Hyper/.hyper.js |
Note : config à ~/.hyper.js
toujours supporté, mais sera ignoré, si config dans le répertoire d’application présent. Sinon, elle sera déplacée dans le répertoire d’application lors de la première exécution.
L’objet config
vu ci-dessus dans .hyper.js
admet ce qui suit
Propriété | Défaut | Description |
updateChannel |
« stable » | Le canal de mise à jour pour recevoir les mises à jour de |
fontSize |
12 | La taille par défaut en pixels pour le terminal |
fontFamily |
« Menlo, DejaVu Sans Mono, Lucida Console, monospace » | La famille de polices à utiliser avec les fallbacks optionnels |
uiFontFamily |
« -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, … » | La famille de polices à utiliser pour l’interface utilisateur avec des replis optionnels |
fontWeight |
« normal » | Le poids de la police par défaut : « normal » ou « gras » |
fontWeightBold |
« gras » | Le poids de la police pour les caractères gras : « normal » ou « gras » |
cursorColor |
« rgba(248,28,229,0.8) » | La couleur du curseur dans le terminal |
cursorAccentColor |
« #000 » | La couleur du texte sous le curseur BLOCK |
cursorShape |
« BLOCK » | La forme du curseur dans le terminal. Les options disponibles sont : ‘BEAM’, ‘UNDERLINE’, ‘BLOCK’ |
cursorBlink |
« false » | Si vrai, le curseur clignotera |
foregroundColor |
« #fff » | Couleur du texte principal du terminal |
backgroundColor |
« #000 » | Couleur et opacité du fond de la fenêtre et du terminal principal |
selectionColor |
« rgba(248,28,229,0.3) » | Couleur de fond/opacité de la sélection de texte dans le terminal |
borderColor |
« #333 » | Couleur de la bordure de la fenêtre principale et de la barre d’onglets |
css |
« » | CSS personnalisé à inclure dans la fenêtre principale |
padding |
« 12px 14px » | Valeurs de remplissage CSS pour l’espace autour de chaque terme |
colors |
{ black : « #000000 », rouge : « #ff0000 », … } | Une liste de surcharges pour la palette de couleurs. Les noms des touches représentent les « ANSI 16 », qui peuvent tous être vus dans la configuration par défaut. |
shell |
« » | Un chemin vers un shell personnalisé à exécuter lorsque Hyper démarre une nouvelle session |
shellArgs |
« » | Un tableau d’arguments de shell |
env |
{} | Un objet de variables d’environnement à définir avant le lancer le shell |
windowSize |
La largeur/hauteur par défaut en pixels d’une nouvelle fenêtre | |
scrollback |
1000 | Le nombre de lignes à persister dans le tampon du terminal pour le défilement |
copyOnSelect |
false | Si vrai, le texte sélectionné sera automatiquement copié dans le presse-papiers |
quickEdit |
false | If true, sur un clic droit, le texte sélectionné sera copié ou collé si aucune sélection n’est présente (vrai par défaut sur Windows) |
defaultSSHApp |
true | Si vrai, Hyper sera défini comme le client de protocole par défaut pour SSH |
modifierKeys |
{altIsMeta : false} | Changer le comportement des touches modificatrices pour qu’elles agissent comme une clé méta |
showHamburgerMenu |
true sur Linux/Windows, false sur macOS | Changer la visibilité du menu hamburger. Les options disponibles sont : true, false |
showWindowControls |
« » | Changer la position/visibilité des contrôles de la fenêtre. Les options disponibles sont : true, false, « left » |
Extensions API
Les extensions sont des modules Node.js universels chargés à la fois par Electron et le processus de rendu.
Le système d’extension est conçu autour de la composition des API que nous utilisons pour construire le terminal : React
composants et Redux
actions.
Au lieu d’exposer une méthode ou un paramètre d’API personnalisé pour chaque point de personnalisation possible, nous vous permettons d’intercepter et de composer chaque bit de fonctionnalité !
Les seules connaissances qui sont donc nécessaires pour étendre avec succès Hyper
sont celles de ses bibliothèques open source sous-jacentes.
Vous trouverez des détails supplémentaires sur le développement de plugins dans le dépôt Hyper.
Votre module doit exposer au moins une de ces méthodes :
Méthode | Invoquée depuis | Description | ||||||
onApp |
Electron |
Invoquée au premier chargement de l’application. Si un plugin se recharge, il est invoqué à nouveau avec l’app existante. Paramètres:
|
||||||
onWindow |
Electron |
Invoquée à la création de chaque fenêtre. Si un plugin se recharge, il est invoqué à nouveau avec les fenêtres existantes. Paramètres:
|
||||||
onUnload |
Electron |
Invoqué lorsqu’un plugin est supprimé par l’utilisateur. Paramètres:
|
||||||
decorateConfig |
Electron / Renderer |
v0.5.0+. Permet de décorer la configuration de l’utilisateur. Paramètres:
|
||||||
decorateEnv |
Electron |
v0.7.0+. Permet de décorer l’environnement de l’utilisateur en renvoyant un objet environnement modifié. Paramètres:
|
||||||
decorateMenu |
Electron |
Invoqué avec le modèle Paramètres:
|
||||||
decorateBrowserOptions |
Electron |
Vous permet de décorer les options Paramètres:
|
||||||
onRendererWindow |
Renderer |
Invoqué lors du premier chargement ou du rechargement ultérieur d’un plugin dans chaque fenêtre. Paramètres:
|
||||||
middleware |
Renderer |
Un middleware Redux personnalisé qui peut intercepter toute action. Par la suite, nous invoquons le |
||||||
reduceUI reduceSessions reduceTermGroups |
Renderer |
Un réducteur personnalisé pour la forme d’état
|
||||||
getTabsProps |
Renderer |
Passe les props de
|
||||||
getTabProps |
Renderer |
Passe les props de
|
||||||
getTermGroupProps |
Renderer |
Passe les props de
|
||||||
getTermProps |
Renderer |
Passe les props de
|
||||||
mapHyperState mapTermsState mapHeaderState mapNotificationsState |
Renderer |
Un mappeur personnalisé pour les propriétés d’état que les composants du conteneur reçoivent. Notez que pour que les composants enfants obtiennent ces propriétés, vous devez les passer vers le bas en utilisant les méthodes correspondantes (comme Doit retourner un objet étendu de la carte passée.
|
||||||
mapHyperDispatch mapTermsDispatch mapHeaderDispatch mapNotificationsDispatch |
Renderer |
Un mappeur personnalisé pour les propriétés de répartition. Doit retourner un objet étendu de la carte passée.
|
||||||
decorateHyper decorateNotifications decorateNotification decorateHeader decorateTabs decorateTab decorateTerms decorateTermGroup decorateSplitPane decorateTerm
|
Renderer |
Invoqué avec le Paramètres:
|
Chargement de modules
L’utilisateur peut charger et recharger à chaud des plugins en appuyant sur Commande + R (rafraîchir). S’il vous plaît, efforcez-vous de faire des plugins qui ne nécessitent pas un redémarrage complet de l’application pour fonctionner.
Notice
Les plugins affectant la `BrowserWindow` auront l’effet sur les nouvelles fenêtres après le chargement à chaud.
À l’avenir, nous pourrions le faire automatiquement.
Lors du développement, vous pouvez ajouter votre plugin à .hyper_plugins/local
et ensuite le spécifier sous le tableau localPlugins
dans .hyper.js
. Nous chargeons les nouveaux plugins :
- Périodiquement (toutes les quelques heures)
- Lorsque des modifications sont apportées au fichier de configuration (
plugins
oulocalPlugins
) - Lorsque l’utilisateur clique sur Plugins > Update all now
Le processus de rechargement implique
- L’exécution de
npm prune
etnpm install
dans.hyper_plugins
. - Exécuter les
require.cache
dans l’électron et le processus de rendu - Invoquer les méthodes
on*
sur les instances existantes et rendre à nouveau les composants avec les décorations fraîches en place.
L’emplacement des plugins
macOS | ~/Library/Application Support/Hyper/.hyper_plugins |
Windows | $Env:AppData/Hyper/.hyper_plugins |
Linux | ~/.config/Hyper/.hyper_plugins |
Note : les plugins à ~/.hyper_plugins
sont toujours supportés, mais seront ignorés, si les plugins du répertoire d’application sont présents. Sinon, ils seront déplacés vers le répertoire d’application lors de la première exécution.
Note : sur le processus principal, les plugins sont enregistrés dès que possible (nous tirons onLoad
). Sur le navigateur, c’est à l’utilisateur de déclencher leur chargement en appuyant sur command+R. Nous mettons l’utilisateur au contrôle du chargement de cette façon pour éviter qu’il ne perde un travail critique par des extensions qui réinitialisent l’état ou ne le préservent pas correctement.
Décoration des composants
Nous vous donnons la possibilité de fournir un composant d’ordre supérieur pour chaque pièce de l’interface utilisateur Hyper
.
Sa structure est la suivante :
<Hyper> <Header> <Tabs> <Tab /> ... </Tabs> </Header> <Terms> <TermGroup> <SplitPane> <TermGroup> <Term /> ... </TermGroup> <TermGroup> <Term /> ... </TermGroup> </SplitPane> </TermGroup> </Terms> <Notifications> <Notification /> ... </Notifications></Hyper>
Toutes les méthodes decorate*
reçoivent les références suivantes dans un objet passé en second paramètre :
React |
L’ensemble de l’espace de noms React. |
notify |
Une fonction d’aide qui affiche une notification de bureau. Le premier paramètre est le titre, le deuxième est le corps optionnel de la notification et le troisième est un autre paramètre optionnel qui peut être utilisé pour enregistrer les détails dans la console de développement. Pour passer ces détails, il suffit de fournir et objet avec une propriété |
Notification |
Le composant Notification au cas où vous voudriez le réutiliser. |
Tous les composants acceptent les deux propriétés suivantes pour étendre leur balisage:
customChildren |
Un tableau de Element ou un seulElement à insérer en bas du composant. |
customChildrenBefore |
La même chose que la propriété ci-dessus, mais insérée comme le ou les premiers éléments enfants du composant. |
Votre composant d’ordre supérieur peut fournir une onDecorated
propriété au composant décoré pour obtenir une référence à son instance.
Votre composant d’ordre supérieur Term peut fournir une propriété onCursorMove
handler qui sera appelée lorsque le curseur s’est déplacé avec un paramètre objet représentant sa position relative à l’origine Term :
x |
Position horizontale en pixels |
y |
Position verticale en pixels |
width |
La largeur du curseur en pixels |
height |
Hauteur du curseur en pixels |
col |
Position horizontale en colonnes |
row |
Position verticale en rangées |
Nous vous encourageons à maintenir la compatibilité avec les autres décorateurs. Puisque beaucoup peuvent être définis, ne supposez pas que le vôtre est le seul.
Par exemple, si vous passez des enfants, composez des valeurs potentielles existantes:
render () { const customChildren = Array.from(this.props.customChildren) .concat(<p>My new child</p>); return <Tab {...this.props} customChildren={customChildren} />}
Ou si vous utilisez la propriété onDecorated
onDecorated (term) { this.term = term; if (this.props.onDecorated) { this.props.onDecorated(term); }}
Actions et effets
Toutes les actions Redux sont disponibles pour que vous les manipuliez à travers votre middleware et vos réducteurs. Pour un exemple, consultez le plugin de référence Hyperpower.
Les effets secondaires se présentent sous deux formes fondamentales :
- Certaines actions répartissent d’autres actions en fonction de l’état.
- Certaines actions font un travail asynchrone en communiquant sur le canal RPC au processus principal
Dans tous les cas, l’effet secondaire est passé comme la clé effect
dans l’action et plus tard géré par notre middleware.
Cela signifie que vous pouvez surcharger, composer ou éliminer complètement les effets ! En d’autres termes, c’est ainsi que vous pouvez modifier la fonctionnalité ou le comportement par défaut de l’application.
À titre d’exemple, considérez l’action que nous utilisons pour augmenter la taille de la police lorsque vous appuyez sur 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 }); } }); };}
Le terminal sous-jacent
Hyper
atteint une grande partie de sa vitesse et de ses fonctionnalités grâce à la puissance de xterm.js
Autres API
Les objets Electron app
sont étendus avec les propriétés suivantes :
config |
Un Object avec le bloc config de .hyper.js . |
plugins |
Un Object avec des aides pour les plugins. |
getWindows |
A Function qui renvoie un Set de toutes les fenêtres ouvertes. |
createWindow |
A Function qui va créer une nouvelle fenêtre. Accepte un callback facultatif qui sera passé comme init callback de la nouvelle fenêtre. |
Les objets Electron BrowserWindow
sont étendus avec les paramètres suivants :
rpc |
Un EventEmitter qui permet la communication avec le processus de fenêtre. |
sessions |
Un Map de Session objets qui détiennent la communication avec les pty de chaque terme. |
Les fenêtres de rendu sont pareillement étendues avec:
rpc |
Un EventEmitter qui permet la communication avec le processus de la fenêtre. |
store |
L’objet Redux Store . Il permet d’accéder aux actions dispatch ou de lire l’état global avec getState . |
L’objet rpc
est symétrique entre le navigateur et le processus de rendu. L’API est la même que celle de Node.js, à l’exception qu’elle n’admet qu’un seul objet comme paramètres uniquement :
window.rpc.emit('hi there', { some: 'payload', any: });
Exemple de thème : Hyperyellow
L’extension suivante modifie simplement la configuration pour ajouter des CSS et des couleurs jaunes ! Voici le code.
Les thèmes sont simplement des plugins ! Un seul crochet, decorateConfig
est nécessaire:
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; } ` });}
J’ai saisi les noms de classe en inspectant le terme avec Devtools, que vous pouvez déclencher à partir de View -> Toggle Developer Tools
. Lorsque vous le faites, remarquez que certaines classes sont générées automatiquement et suivies d’un nonce aléatoire (par exemple : term_13hv8io
). Ignorez-les : elles changent avec chaque nouvelle fenêtre !
Notez l’accent mis sur le fait de bien jouer avec les autres extensions. Plus précisément, nous créons un nouvel objet, nous n’étendons que les clés qui nous intéressent, et nous composons le CSS pour préserver le réglage de l’utilisateur et celui des autres auteurs :
return Object.assign({}, config, { css: ` ${config.css || ''} /* your css here */ `});
Exemple d’extension : Hyperpower
L’extension suivante rend les particules au fur et à mesure que le curseur se déplace :
Promenons-nous dans son code.
D’abord, nous interceptons l’action Redux SESSION_ADD_DATA
. Vous pouvez trouver la liste complète des actions dans le référentiel.
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); }};
Notez que nous ne re-dispatchons pas l’action, ce qui signifie que nous ne rendons jamais la sortie de la commande au terminal. Au lieu de cela, nous expédions une action propre, que nous saisissons dans le uiReducer
et que nous mappons plus tard :
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 });};
Nous voulons ensuite décorer le composant <Term>
afin de pouvoir accéder au caret sous-jacent.
Cependant, <Term>
n’est pas un conteneur auquel nous pouvons mapper des props. Nous utilisons donc getTermProps
pour passer la propriété plus bas:
exports.getTermProps = (uid, parentProps, props) => { return Object.assign(props, { wowMode: parentProps.wowMode });}
L’extension renvoie alors un composant d’ordre supérieur pour envelopper <Term>
. Remarquez que nous passons la propriété onDecorated
pour accéder au composant Term de base et à son DOM ref, et la propriété onCursorMove
pour utiliser l’API du curseur Hyper:
render () { return React.createElement(Term, Object.assign({}, this.props, { onDecorated: this._onDecorated, onCursorMove: this._onCursorMove }));}
.