TextMacros
muqaddar
Administrateur
En fait, je me demande comment vous gérez vos bouts de code vous ?
Vous les stockez quelque part ?
Perso, je suis tjs en train de me dire : "dans quelle appli j'ai déjà écrit ça ?"
Vous les stockez quelque part ?
Perso, je suis tjs en train de me dire : "dans quelle appli j'ai déjà écrit ça ?"
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
J'ai un dossier plein de petits projets bidons aux noms évocateurs qui ont très peu de code...
par exemple j'ai un TextMacro pour iPhone qui me taper et me préremplit les méthodes de UIResponder touchBegan/touchMoved/touchEnded/touchCancelled, un autre qui me génère du code pour récupérer la liste des images d'un certain type dans un dossier de ressources du bundle de mon appli, ce genre de choses.
J'ai juste à taper dans le code "touch" et à appuyer sur la touche echap, et parmi les complétions, il me propose "touch methods definitions" (car dans mon TextMacro j'ai associé mes 4 méthodes préfaites au completionPrefix "touch" et au nom "touch methods definitions").
J'en ai plein comme ça, c'est vraiment hyper pratique : pas besoin d'aller chercher dans un autre projet, on sait jamais trop lequel en plus, pour savoir où on a déjà utilisé ce genre de code : je tape le mot clé que j'ai choisi, la touche "esc", et hop, tout est prêt, avec même si besoin les "placeholders" au bon endroit... j'adore
Sinon y'a une autre possibilité que les TextMacros, c'est d'utiliser les "User Scripts" que j'ai redécouvert récemment grace à schlum (si je ne me trompe pas)... à la base c'est fait pour exécuter des scripts Unix, mais rien ne t'empêche d'écrire un script... qui se contente d'écrire du texte. Que ce soit un script AppleScript, ou un script shell en utilisant "#!/bin/cat" comme première ligne... voire "#!/usr/bin/tail +2" comme première ligne, pour qu'il t'affiche le contenu du script... à partir de la 2e ligne (donc en évitant de te recopier la première ligne justement "#!/usr/bin/tail +2"). Après tu peux utiliser certains mots clés entre %%%{...}%%% (cf la doc sur les user scripts) qui seront remplacés à la volée par leur valeur (nom du fichier courant, contenu de la sélection, ...)
Mais bon je trouve de loin la solution des TextMacros carrément confortable, personnellement j'en use et abuse à foison pour taper mon code et y insérer tout plein de blocs de code préparés à l'avance et prêts à l'usage.
C'est vrai que c'est une bonne idée.
Mais tu fais un rangement de tes macros ?
J'ai un autre fichier de définitions orienté iPhone, avec les touchBegan/Moved/Ended/... ou le modèle de définition de méthodes comme tableView:cellForRowAtIndexPath: etc..., un autre un peu plus générique (par exemple pour insérer des "// MARK:" qui font ajouter des marques dans mon menu de méthodes, entourés de lignes séparatrices, etc)...
Et pour chaque fichier TextMacro que je crée (je pourrais tous les mettre dans un seul mais je trouve ça plus propre de les séparer), j'associe un menu. Ce qui fait que dans le menu "Edit > Insert Text Macro", j'ai plusieurs sous-menus personnalisés, genre un menu "Protocols", un menu "iPhone Methods", etc...
Donc après, soit je connais par coeur le "completionPrefix" que j'ai associé à mon bloc de code, donc je tape le début (genre "touch<esc>" pour les méthodes de UIResponder), soit je ne m'en souviens plus et j'ai alors juste à aller dans Edit > Insert Text Macro et à chercher dans les bons sous-menus (voire sous-sous-menus si j'avais envie de créer une arborescence plus profonde) le nom descriptif de mon extrait de texte pour le sélectionner et qu'il insère le bloc de code correspondant.
Alors si je fais cela à partir de l'éditeur de script (menu des scripts), comment je définis ce que tu appelles le completionPrefix : Il ne me complète rien après draw ou drawRect ?
J'ai bien vu le post d'Aridon mais ce serait mieux si on pouvait tout faire par l'interface graphique.
[EDIT] avec la syntaxe heredoc , la deuxième image
1) Non quand je parlais des "User Scripts" ce ne sont vraiment que des scripts qu'il faut choisir de lancer... soit en les sélectionnant depuis le menu script, soit en utilisant leur raccourci clavier que tu as défini depuis la palette "Edit User Scripts..." que tu as mise en capture.
2) Pour la petite astuce, pour ton exemple de script, quitte à utiliser /bin/sh et une commande ensuite pour l'affichage (ici "echo"), je ne sais pas si tu connais la syntaxe heredoc qui a l'avantage d'éviter d'avoir à mettre entre guillemets... et donc d'avoir à échapper ton code : Bon c'est sûr pour ton exemple avec le "echo" qui n'a pas de guillemets, ça n'a pas d'incidence, mais c'est bon de savoir que la possibilité existe quand on se met à faire ce genre de scripts.
D'ailleurs dans la doc Apple des User Scripts, ils en mettent un exemple aussi.
3) Sinon quand j'ai évoqué la possibilité d'utiliser les User Scripts, c'était juste une alternative possible à laquelle j'avais pensée, et qui a l'avantage de pouvoir (1) facilement rajouter des scripts via une interface graphique dispo dans Xcode et (2) rajouter des raccourcis claviers à ces scripts.
Mais perso je n'utilise pas ces User Scripts pour ça, je n'utilise que les TextMacros (qui sont donc autre chose, rien à voir avec les User Scripts), pour lesquels tu peux rajouter du texte mais moins facilement (et nécessite de relancer Xcode pour qu'ils soient pris en compte, pas pratique au début quand tu en rajoutes plein) et n'ont pas d'interface graphique pour le faire*. Tu peux leur affecter un raccourci clavier aussi, via les préférences "Key Bindings" de Xcode, comme pour les autres menuitems en fait, donc de ce côté pas de différence... mais ils ont l'avantage d'avoir, contrairement aux User Scripts, un "completion prefix" (normal, les User Scripts à la base c'est pas forcément fait pour ça, du moins pas que pour l'insertion de texte, mais plutôt pour traiter/modifier une sélection (la (dé-)commenter par exemple)...
*tiens ça pourraà®t être un projet, d'autant que c'est pas méchant à faire le format xctxtmacro n'est rien d'autre qu'un fichier plist, au format ASCII/Text (d'ailleurs j'ai jamais essayé avec un fichier plist XML, j'ai toujours vu que des xctxtmacro en format texte donc j'ai toujours fait pareil
Non je connaissais pas et c'est effectivement pratique de ne pas se farcir les échappements. Le double chevron, c'est une simple syntaxe des scripts ou c'est une redirection comme cat > unFichier ?
Le "<<" est à la base un symbole de redirection du shell... mais en fait fait partie de la syntaxe here-doc : j'ai jamais trouvé de doc claire à ce sujet, mais de ce que j'ai compris, c'est une sorte d'extension à l'opérateur de redirection "<<" (déjà que l'opérateur "<<" et peu connu et encore moins "<<<", ça explique peut-être le peu de notoriété de heredoc ?) : derrière le "<<" tu mets un identifieur quelconque, et dans ce cas toute les lignes qu'il y a après, et ce jusqu'à l'identifieur utilisé après les "<<", est considéré comme le stream utilisé en entrée.
En gros, au lieu d'utiliser "<<<" et de mettre directement le flux de texte à envoyer au stdin du programme derrière (comme tu peux le faire pour "cat <<<Bonjour" qui au lieu d'afficher le contenu d'un fichier d'après son nom, va afficher le contenu de stdin... auquel tu fournis directement le texte "Bonjour" dans la foulée, et sortir, donc cette commande est équivalente à un "echo Bonjour" en somme pour le coup), tu utilises "<<MACHIN" puis tu mets tout le texte que tu veux et tu termines par un autre "MACHIN" (se trouvant obligatoirement au début d'une nouvelle ligne, sans espace ni tablulations avant, et seul sur la ligne) et tout le texte entre "<<MACHIN" et "MACHIN" sera envoyé à l'entrée standard du programme appelant.
Du coup oui c'est une redirection unix, donc dans un sens "<<" fait partie de la syntaxe heredoc, ou plutôt heredoc est une syntaxe de redirection comme une autre.
Du coup si tu utilises Ca aura le même effet (pour le coup puisqu'il n'y a qu'une seule ligne) que "cat <<<salut", ou dans ce cas là puisque j'ai pris "cat" comme exemple, ça reviendra au même qu'à un "echo salut" aussi.
Bon je suis allé chercher le modèle ObjectiveC.xctxtmacro dans l'appli XCode, et j'en ai fait un perso iPhone.xctxtmacro
Je vais le mettre dans
~/Library/Application\ Support/Developer/Shared/Xcode/specifications/
Les identifier, name ont une importance ?
[EDIT] Ah oui, l'Identifier principal doit être reporté sur les clés BasedOn
uivc marche bien mais pas draw ?
[EDIT] Ok, maintenant c'est bon, je m'étais trompé sur IncludeContexts = ( "xcode.lang.objc" );Â en laissant IncludeContexts = ( "xcode.lang.objc.block" );
C'est quoi ce champ IncludeContexts ?
Donc, infos en vrac sur les TextMacros :
1) Le format des fichier xctxtmacros est assez simple, en somme c'est un PLIST au format ASCII/text (les fichiers xctxtmacros sont même lisible avec Property List Editor)
2) Un fichier xctxtmacro consiste en un NSArray de NSDictionary, chaque item NSDictionary définissant typiquement une "Text Macro" avec son texte, son nom, son identifieur, son completionPrefix...
3) Mais ces items (ces NSDictionaries) peuvent définir des liens "d'héritage" (via la clé "BasedOn" et sa valeur indiquant l'identifier de l'item dont on veut hériter), et du coup certains items peuvent ne définir que des clés communes mais pas réellement une TextMacro à proprement parler (par exemple ça peut être utilse pour définir des propriétés communes à plusieurs TextMacros qui vont "hériter" de cet item), c'est le cas par exemple typique d'un item définissant un sous-menu dans le menu "Insert Text Macro" (mais ça ne se limite pas forcément qu'à ça)
4) J'ai trouvé quelques infos plus détaillées dans le PDF que j'ai trouvé dans l'image disque "Bonus Sections Disk Image" téléchargeable sur cette page (liée au bouquin "Beginning Xcode"), et que je vous conseille de lire aussi. Le PDF décrit le format des fichiers xctxtmacros et donne la définition des clés utilisées dans les NSDictionaries.
J'y ai aussi appris l'existance d'une clé "CycleList" qui peut s'avérer utile pour grouper plusieurs variantes d'une TextMacros dans une seule (quand on resélectionne cette TextMacro dans le menu "Insert Text Macro" une 2e fois juste après la première, ça fait la 2e variante, etc...)
5) Il y a aussi des infos intéressantes sur lesquelles je suis tombé sur ce thread dans la mailinglist apple et les suivants.
Une des choses que j'y ai apprises (et que je cherchais depuis quelques temps), c'est où trouver la liste des valeurs possibles pour les clés "IncludeContexts" et "ExcludeContexts" qui se trouvent définies dans les fichiers xclangspec (un "find" m'a permis de les localiser dans le dossier [tt]/Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources[/tt]). Ce sont eux aussi des fichiers au format plist textuel, après la signification de chaque clé est un peu empirique voire barbare à comprendre (ça définit une syntaxe BNF avec les délimiteurs de début et de fin par exemple, etc...) et je vous avoue que j'ai pas vraiment décortiqué ces fichiers... d'aileurs je ne suis pas sûr qu'il y en ait un grand intérêt. Mais l'intérêt de regarder ces fichiers est qu'on a au moins la liste de tous les noms des contextes possibles utilisables, et comme ces noms sont suffisemment explicites en eux-mêmes, c'est déjà bien !
Bon après en général ceux que l'on voit communément utilisés dans les xctxtmacros fournis avec Xcode sont bien suffisants.
----
Voilà pour les pistes en vrac... Si y'a des volontaires pour commencer le dev d'une GUI pour l'édition des xctxtmacros...
Moi j'ai bien ma petite idée de GUI mais je ne pense pas avoir bcp de temps pour m'y mettre avant qques jours. J'ai quand même fait un shot dans IB (cf capture ainsi que XIB joint) pour montrer comment je voyais la GUI si on se lance là dedans... c'est ouvert aux critiques bien sûr mais c'est pour vous donner envie
Après on peut toujours créer ses TextMacros avec Property List Editor j'imagine, faut juste connaà®tre la signification des clés, donc une GUI spécialisée comme celle-là donnerait sans doute plus envie, non ?
Pour l'instant ce que le soft sait faire :
1) Lire des fichiers xctxtmacro et les parser
2) analyser pour détecter les dépendances/hiérarchies et ainsi afficher la NSOutlineView de façon hiérarchique, et ce même si le parent (identifier indiqué dans la clé "BasedOn") d'une définition n'apparaà®t qu'après ladite définition, ou si l'identifier indiqué dans "BasedOn" n'est pas défini dans le fichier analysé (exemple typique, si c'est "BasedOn=objc", objc étant une définition présente dans les TextMacros intégrées à Xcode).
Ces "définitions externes" (comme la def "objc", celle qui ne sont pas présentes dans le fichier analysé " mais dans un autre fichier " mais dont héritent des définitions du fichier analysé) sont affichés sous un style particulier avec un fond grisé, et ne sont pas sélectionnables : elles ne sont là que pour pouvoir représenter l'aspect hiérarchique/d'héritage des définitions qui les utilisent.
3) Sur clic dans la NSOutlineView, affiche l'identifier, le nom, le completionPrefix, le texte à insérer, si l'entrée apparaà®t dans le menu de Xcode ou pas, et si c'est vraiment une macro ou juste un élément pour décrire la présence d'un sous-menu.
Ce que le soft ne gère pas encore :
1) Les tableaux en bas de la zone de détails : ComputerLangages, DefaultDefinitions, IncludeContexts, ExcludeContexts
2) L'affichage des valeurs déduites de l'héritage (mais bon l'espèce de principe d'héritage des macro definitions est surtout utilisé avec ComputerLangages, DefaultDefinitions et les contextes, qui ne sont pas encore prêts, alors bon...
3) Les CycleList (je ne sais pas si je vais les implémenter d'ailleurs ?) ; j'ai même pas encore prévu d'élément d'interface encore pour ça.
4) Et surtout la sauvegarde des modifications : pour l'instant aucune modification de contenu faite sur l'interface (modification du contenu d'un TextField genre Name ou Identifier, ou du TextString à insérer) n'est prise en compte, je n'ai implémenté que la lecture encore.
Mais déjà ça peut vous donner une idée : il vous suffit d'ouvrir un de vos fichiers xctxtmacro et me valider que l'affichage de la NSOutlineView est cohérente, ainsi que les détails affichés quand on clique sur un élément de ladite NSOutlineView.
Si vous avez des remarques, des conseils sur l'interface ou autre, des demandes, des idées... ou voulez avancer sur le projet à votre tour, c'est totalement libre donc tout retour est bienvenu
Je teste à un moment non occupé de ma journée !
J'ai pensé à la possibilité, mais pour moi ça ne viendra que plus tard.
Pour l'instant je fais un peu de refactoring car j'avais tout mis dans un seul AppController, donc j'ai fait une partie modèle pour représenter mes définitions ce qui est bcp plus propre...
Je vais commencer par faire en sorte qu'on puisse modifier les définitions (enfin... que la modification des champs soit sauvegardée quoi) et qu'on puisse ajouter et supprimer des définitions (j'ai oublié des boutons "+" et "-" autour de l'OutlineView dans mon interface tiens ) et enfin... sauvegarder le résultat en réécrivant le plist (j'ai testé même si le fichier xctxtmacro est en XML ça marche aussi ça reste un PLIST que sait parser Xcode donc c'est bon)
Après, le double-open, la gestion des items de la menubar, et les petits plus, ça viendra au fur et à mesure, mais je vais d'abord m'atteler à faire un truc un minimum fonctionnel pour qu'on puisse l'utiliser rapidement mm s'il manque 2-3 petits "plus" qui viendront en V2
La difficulté du double-open (de pouvoir ouvrir plusieurs xctxtmacros et mélanger leurs définitions) c'est surtout la question des priorités : en effet Xcode parse les domaines dans un certain ordre(Bundle de Xcode, NSSystemDomain, NSUserDomain, NSLocalDomainMask), et la redéfinition d'une définition avec le même Identifieur permet de "surcharger" cette définition... Encore faut-il donc gérer ce genre de cas donc (d'autant qu'en interne j'utilise un NSDictionary dans mon modèle pour pouvoir accéder facilement aux définitions d'après leur Identifier...)
---
Tiens question en passant, comment on peut faire dans IB le genre de barre à boutons qu'on voit souvent sous les TableViews dans les softs Apple, souvent avec un bouton "+" et un bouton "-", voire même parfois un bouton avec la roue dentée aussi ? (par exemple dans les préférences système "Réseau" sous la liste des interfaces, ou dans Mail sous la liste des BAL, etc) ? Je vois pas de widget tout fait dans IB pour faire ça ?
Oui ou/(et en option) que tous les fichiers dans specifications viennent s'ajouter à la'outline view
Des squares buttons , un segmented control , ou pop up pull down-square pour la roue ...
Si par exemple tu veux créer de nouvelles définitions de TextMacros, il les ajoutera à quel fichier ? Et si tu veux séparer des définitions en 2 ou plusieurs fichiers ?
Et comment présenter les choses ? Mettre dans mon "OutlineView" à la racine la liste des fichiers, et quand on ouvre on y trouve les définitions que contient le fichier ? Mais du coup c'est plus possible d'avoir la représentation hiérarchique car rien n'empêche d'avoir une définition dans le fichier 1 qui hérite d'une définition du fichier 2...
Là l'avantage de la présentation courante de la OutlineView en plus c'est qu'elle reflète l'arborescence qu'on aura dans le menu dans Xcode, en plus de la notion d'héritage (qui est liée d'ailleurs).
Alors sinon je pourrais tjs rajouter dans la zone de détails à droite un menu déroulant pour choisir dans quel fichier enregistrer la macro, avec un menuitem spécial "Add..." dans ce dropdown... Mais si on veut réorganiser les définitions (par exemple prendre tout plein de définitions et les séparer dans un fichier à part) c'est pas pratique...
Bref je réfléchirai à tout ça quand j'en serais à cette problématique, lors de la V2, mais tu vois que c'est pas si simple à la base :P donc chaque chose en son temps
PS : Merci pour les SquareButtons, j'avais essayé avec différents styles, dont les Bevel et Square, mais j'arrivais pas à retrouver le style que je voulais... j'ai rebidouillé avec des SquareButtons et j'ai fini par obtenir l'effet voulu
Côté fonctionnalités, pas grand chose de neuf (les modifications ne sont toujours pas prises en compte), mais un gros refactoring de fait pour rendre ça propre et MVC (avant j'avais tout dans le AppDelegate, c'était mal , mais now mon AppController est juste pour gérer l'interface, et j'ai un Controller pour gérer chacune de mes Table/OutlineViews, et surtout une classe "DefsModel" pour gérer le modèle de définitions... 10x plus propre tout ça)
J'ai modifié l'interface aussi (des splitviews un peu partout, les boutons d'ajout/suppression de Include/ExcludeContexts ou de TextMacros plus zoulis, ...) et rajouté l'affichage des langages du TextMacro sélectionné (même si je suis pas satisfait de la colonne avec checkbox mais j'ai pas encore eu le temps de regarder comment la mettre en première colonne)... mais il reste encore pas mal à faire (j'ai mis des marqueurs "// TODO:" partout dans le code ) pour afficher toutes les infos, pouvoir les modifier ou ajouter des entrées... et pouvoir sauver.
Donc ça avance doucement mais sûrement :P (surtout que maintenant que j'ai une archi bien plus propre, c'est bien plus facile y compris si vous voulez regarder un peu le code voire y apporter votre contribution )
Le projet refactoré en PJ.
Un script Apple dans les user scripts pour faire un relaunch XCode ? ou une simple réinitialisation ?
Je n'ai pas regardé s'il y avait un moyen de demander à Xcode de relire les "TextMacro Specifications" à la volée... Pour moi il faut quitter et relancer Xcode pour qu'il les prenne en compte... mais en fait je m'étais même pas posé la question, donc j'ai même pas cherché ::)
Je pensais prévoir un bouton qui permettrait de relancer Xcode depuis mon appli, pour que ce soit pris en compte... On peut toujours y rajouter de l'AppleScript qui va mémoriser le ou les projets ouverts avant de quitter et relancer... et les réouvrir, à la limite. Mais bon j'en suis pas là .
Suite du projet : avis aux reprenneurs
Alors par contre j'avais déjà pas bcp de temps pour avancer, mais là à partir de la semaine prochaine je suis sur un nouveau projet iPhone pour le taf et ne vais avoir encore moins de temps...
Donc en attendant je vous remet le bébé, n'hésitez pas à télécharger le projet Xcode et à taper dedans à votre tour pour avancer.
J'ai mis des "TODO" un peu partout pour les trucs pas encore faits, et je pense que mon code est à peu près clair. Le principal RAF avant d'avoir un truc un minimum utile/utilisable (v1.0) :
Après il restera toujours pour la suite :
- la gestion des DefaultSettings et paufiner l'ensemble (v1.1) pour avoir un truc totalement fonctionnel
- Ajouter des fonctionnalités pratiques en v2.0 (comme ouvrir automatiquement tous les fichiers xctxtmacros parsés par Xcode... avec les interrogations qui vont avec déjà évoquées de priorité et de trouver une GUI qui va bien)
Voilà , y'a encore du boulot, vraiment rien de bien méchant mais le truc c'est qu'il faut juste trouver le temps pour le faire, et comme pour ma part ça va être plus dur dans les semaines à venir, si vous (surtout toi Philippe à priori) voulez avancer de votre côté, n'hésitez pas...
J'ai fait un script (cela fait 10 ans que je n'ai pas touché à AppleScript) dans les Users Scripts , qui ne veut pas fonctionner
Ce script est bien exécuté par le shell, et non en tant que fis du processus XCode ?
Ton script marche dans un shell ? (quand tu l'enregistres dans un fichier et le lance par le terminal) ?
Sinon il me semblais (jamais essayé mais vu dans les menus) que dans les User Scripts on pouvait aussi ajouter des AppleScripts directement ? Ainsi que des flux Automator (qui peuvent d'ailleurs exécuter du code AppleScript brut eux aussi, entre autres)... Donc peut-être regarder avec cette alternative ?
oui cela a l'air
% osascript <<ENDOFSCRIPT
> tell application "XCode" to quit
> ENDOFSCRIPT
% cat > script
tell application "XCode" to quit
% osascript script
avec ce texte dans le .xctxtmacro
Les deux mots <#action#> sont synchronisés : il suffit d'en écrire un pour que l'autre se change !
La première fois que ça m'est arrivé " et que j'ai découvert cette "cerise sur le gâteau" au passage comme tu dis (je viens d'apprendre un idiome anglais que je ne connaissais pas, merci pour ma culture ;D)... j'ai de suite trouvé ça moins pratique :P
Autre élément pratique, la mise en page (retour à la ligne, tabulations) dans le fichier du text macro se reporte aussi. Il n'est donc pas nécessaire d'utiliser \n et \t, et on peut avoir une disposition WYSIWYG.
Pour l'instant, je n'ai eu à échapper que les guillemets.
Interface encore un peu modifiée, avec un TabBar pour les tableaux Languages/DefaultSettings/Contexts (et il sera facile dans la V2 de rajouter les CycleLists)
RAF pour la v1.0 :
Je sais, y'a toujours pas la sauvegarde des données, mais en mm temps ça avance quand même... On va pouvoir sous peu attaquer les points 2 et 3 qui permettent de vraiment modifier le fichier (et pas juste le lire, donc), et une fois ces points codés, la v1.0 sera très proche...
Pour la v1.1 :
(Voir comment les présenter pour qu'on ne puisse pas les supprimer (puisqu'héritées), mais qu'on puisse "overrider" leur valeur si on veut... présentation avec la clé en gras si modifiée, comme dans les "Build Settings" des projets Xcode par exemple ?)
Pour la v1.2 :
Pour plus tard :
Voilà , à suivre...