Question
Je voudrais créer une interface utilisateur sous forme de menu contextuel , menu contextuel similaire à celui utilisé dans Magit .
Caractéristiques
Définition de Popup
Une fenêtre contextuelle dans le contexte de cette question signifie une petite fenêtre temporaire qui contient une collection d'éléments de menu afin que l'utilisateur puisse sélectionner un et un seul de ces éléments.
Position sur l'écran
La fenêtre contextuelle peut apparaître dans n'importe quelle partie de l'écran, mais il est souhaitable qu'elle soit assez évidente et qu'elle apparaisse donc à côté de la fenêtre actuellement active.
Contenu du tampon contextuel
Les articles doivent être affichés sous forme de joli tableau. Assez est le contexte de la question signifie visuellement attrayant, cet effet peut être plus facilement obtenu en mettant des éléments de menu en rangées droites, voir
complete--insert-string
par exemple. Ce paragraphe sert de clarification supplémentaire, vous pouvez le faire à votre manière, cela ne rendra pas votre réponse incorrecte.
Sélection de l'élément de menu
La sélection devrait être effectuée en appuyant sur une seule touche ou, éventuellement avec une souris (bien que ce ne soit pas si important, les réponses contenant des propositions qui ne prennent pas en charge la souris sont légales). Si vous proposez une solution prenant en charge la souris, veuillez noter que l'utilisateur devrait pouvoir sélectionner un élément de menu de manière intuitive, c'est-à-dire en cliquant avec le bouton gauche sur le choix souhaité.
La souris NB peut être utilisée de nombreuses façons et d'autres manières d'indiquer un choix sont également les bienvenues.
Élimination de Popup
Une fois que l'utilisateur a sélectionné un élément de menu de la manière décrite ci-dessus, le tampon et donc sa fenêtre doivent être supprimés de la vue et supprimés. La fenêtre qui était active avant l'invocation du menu contextuel devrait redevenir active (c'est-à-dire redevenir active).
Valeur retournée et arguments
De préférence, cette conséquence des actions devrait entraîner le retour d'un objet Lisp. L'objet Lisp peut être soit:
nil
- cela indique que l'utilisateur a abandonné le menu contextuel en appuyant sur C-gou d'une autre manière †.string
- chaîne (il est permis d'utiliser un symbole) doit êtrestring-equal
à l'une des chaînes fournies au menu contextuel en tant que collection d'éléments réels.
D'autres manières de faire savoir au reste du programme le choix de l'utilisateur, ou, éventuellement, son absence, sont acceptables. Cependant, si ce n'est pas clair comment cela peut être effectué, je demande à tous les répondeurs d'improviser et ne me demande pas de clarification supplémentaire sur cet aspect.
C'est tout pour la valeur retournée. Quant aux paramètres d'entrée, ils devraient au moins inclure une collection de chaînes qui représentent des choix possibles (c'est-à-dire des éléments de menu).
Réponses acceptables
La réponse attendue peut prendre les formes suivantes:
Extrait de code suffisant permettant au lecteur averti d'écrire une fonction comme celle décrite ci-dessus; il n'est pas prévu ni nécessaire d'écrire toute la fonction de travail. Cependant, pour éviter toute incertitude (des parties considérables du code peuvent-elles être omises?), Je dois noter que les parties manquantes de l'extrait doivent être décrites dans la composante textuelle de la réponse.
Un lien vers une bibliothèque existante qui implémente des fonctionnalités similaires. Pour éviter toute incertitude, je dois noter que similaire dans notre cas signifie que la bibliothèque peut être utilisée pour créer une fenêtre contextuelle (voir la définition ci-dessus) qui a au moins 2 ou 3 fonctionnalités décrites ci-dessus. Si la bibliothèque proposée est différente au point où la condition énoncée précédemment ne peut pas être remplie, chacun de ces cas sera jugé indépendamment et sera toujours voté si OP le juge utile.
Description des fonctions Emacs intégrées ou tierces qui peuvent être utilisées pour implémenter toute fonctionnalité décrite dans la section «Fonctionnalités», voir ci-dessus. Pour éviter l' incertitude de, s'il vous plaît indiquer clairement comment votre réponse peut être utile pour les futurs lecteurs qui souhaitent mettre en œuvre pop - up , menu contextuel semblable à celui utilisé dans Magit .
† Les autres méthodes pour abandonner le menu contextuel peuvent inclure les suivantes (mais sans s'y limiter):
cliquer en dehors de la fenêtre du menu contextuel;
suppression du tampon contenant le popup sans faire de choix.
magit-popup
. Le nouveau package est appelétransient
, et c'est ce qui est utilisé dans les versions actuelles demagit
. Voir magit.vc/manual/transient pour la documentation.Les hydres sont assez simples à écrire:
Hydra est une interface centrée sur le clavier, et dans sa forme de base, ce n'est pas plus difficile que
easy-menu-define
(intégré). Et c'est assez extensible si vous voulez lui faire faire des choses plus complexes.Il suffit de regarder cette interface Twitter, la fenêtre du bas est une Hydra personnalisée, pas beaucoup plus difficile à écrire que celle ci-dessus:
Le code pour cela est disponible sur le wiki , avec beaucoup plus d'exemples.
la source
Après quelques recherches, j'ai trouvé un idiome qui peut être utilisé pour créer une fenêtre en bas (ou même n'importe où) de la fenêtre actuellement active. Cela a lui-même l'effet d'une fenêtre auxiliaire temporaire:
Vous pouvez jouer un peu avec l'
action
argument dewith-current-buffer-window
si vous voulez que le popup apparaisse dans différentes parties de l'écran.La fonction Quit est décrite dans doc-string de
with-current-buffer-window
, elle peut être utilisée pour obtenir des entrées de l'utilisateur. Comme l'a suggéré @tarsius,read-char-choice
est un bon candidat pour l'expérimentation.Le tampon popup lui-même peut être généré comme n'importe quel autre tampon. Je pense toujours aux boutons, car l'utilisateur peut utiliser sa souris pour sélectionner un élément dans le menu contextuel, pas seulement le clavier. Cependant, cela nécessite des efforts supplémentaires si vous voulez bien le faire.
Si votre popup est un peu ad-hoc et que vous n'en aurez pas besoin plus d'une fois, vous pouvez vous en sortir avec cette solution. Jetez également un œil à
completion--insert-strings
. Je l'ai trouvé très utile comme exemple de la façon de générer de jolies lignes d'éléments de menu, vous pouvez même l'utiliser sans modification si vous n'avez pas besoin de quelque chose de spécial.la source
Voici une solution tierce, utilisant Icicles .
Votre code fait apparaître une fenêtre avec les candidats soigneusement organisés sous forme de menu. Pour savoir comment, voir ci-dessous.
Vous préfixez chaque élément de menu avec un caractère unique. Par exemple, a, b, c ... ou 1, 2, 3 ... L'utilisateur frappe le caractère pour choisir l'élément.
Vous liez quelques variables autour d'un appel à
completing-read
. Vous lui passez une liste de vos éléments de menu. Vous pouvez éventuellement spécifier l'un des éléments comme valeur par défaut, choisi si l'utilisateur vient de frapperRET
.Les liaisons de variables indiquent
completing-read
:Vous pouvez rendre les éléments de menu aussi fantaisie que vous le souhaitez (non illustré).
mouse-3
menu contextuel, pour faire quoi que ce soit avec l'élémentVous pouvez également créer des menus à choix vraiment multiples , c'est-à-dire des menus où un utilisateur peut choisir plusieurs éléments en même temps (choisissez un sous-ensemble des choix possibles).
la source
Vous pourriez également être intéressé à regarder le package
makey
. Il est destiné à fournir des fonctionnalités similaires àmagit-popup
, et il s'agit d'un fork du prédécesseur demagit-popup
(magit-key-mode
, mentionné dans le commentaire) à partir du moment où il n'était pas encore un package disponible séparément demagit
.Permettez-moi également de mentionner
discover
: c'est un exemple d'utilisationmakey
(et aussi sa raison d'être). Ce package est destiné à aider les nouveaux arrivants à découvrir les liaisons emacs.Références
makey
etdiscover
par son auteur.magit-popup
été créé dans son propre package.la source
Guide-Key fonctionne bien pour moi pour tous les préfixes configurés.
la source
Basé sur la réponse de @ Drew (Icicles), avec des modifications pour séparer la mise en œuvre du menu des données de menu - de sorte que plusieurs menus pourraient être définis, chacun avec ses propres: (contenu, invite, par défaut).
Cela utilise facultativement le lierre (lorsqu'il est disponible), qui a des fonctionnalités plus avancées telles que la possibilité d'activer des éléments tout en gardant le menu ouvert.
Popup générique.
Exemple d'utilisation, attribuez quelques actions à la touche f12:
la source