├── .gitignore ├── Select Layers by Name.sketchplugin └── Contents │ └── Sketch │ ├── manifest.json │ └── script.cocoascript └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /Select Layers by Name.sketchplugin/Contents/Sketch/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Select Layers by Name", 3 | "description" : "Create a selection based on layer names", 4 | "homepage": "https://github.com/arturmuller/select-layers-by-name", 5 | "author" : "Artur Muller", 6 | "identifier" : "com.example.sketch.30a9184e-e6ec-4f7c-b8b6-3a2e59d99b5d", 7 | "version" : "2.1.0", 8 | "authorEmail" : "me@arturmuller.com", 9 | "compatibleVersion": "3.3.2", 10 | "commands" : [ 11 | { 12 | "script" : "script.cocoascript", 13 | "handler" : "matchExact", 14 | "shortcut" : "cmd /", 15 | "name" : "Match Exact Name", 16 | "identifier" : "select layers by exact name" 17 | }, 18 | { 19 | "script" : "script.cocoascript", 20 | "handler" : "matchPartial", 21 | "shortcut" : "cmd alt /", 22 | "name" : "Match Partial Name", 23 | "identifier" : "select layers by partial name" 24 | } 25 | ], 26 | "menu" : { 27 | "items" : [ 28 | "select layers by exact name", 29 | "select layers by partial name" 30 | ], 31 | "title" : "Select Layers by Name" 32 | } 33 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **BEWARE: This plugin is written in legacy Sketch plugin format and it will not work on new versions of Sketch. I will rewrite this once I have a spare second, so check back later if you're interested in this functionality. (PRs welcome!)** 2 | 3 | # Select Layers by Name 4 | 5 | Create a selection using layer names. The plugin has two commands: 6 | 7 | **Match Exact Name** (⌘/) selects all layers whose name _matches exactly_ the text you have typed. For example, to select a layer called 'New Post' you should type 'New Post' — using only 'New' or 'Post' won't select the layer. 8 | 9 | **Match Partial Name** (⎇⌘/) selects all layers whose name _contains_ the text you have typed. For example, to select a layer called 'New Post' you will get a match by typing 'New', 'Post', 'ew', 'ost', etc... 10 | 11 | Note that both commands are scoped to the _current page_ and are _case insensitive_. 12 | 13 | ## Demo 14 | 15 | _Click image to see demo on YouTube._ 16 | 17 | [![Demo of Select Layers by Name v2.0.0](http://i.imgur.com/5GYIG3E.png)](https://www.youtube.com/watch?v=kgJKhI0SYzg) 18 | 19 | ## License 20 | 21 | Copyright (c) 2015 Artur Muller 22 | 23 | Permission is hereby granted, free of charge, to any person obtaining a copy 24 | of this software and associated documentation files (the "Software"), to deal 25 | in the Software without restriction, including without limitation the rights 26 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 27 | copies of the Software, and to permit persons to whom the Software is 28 | furnished to do so, subject to the following conditions: 29 | 30 | The above copyright notice and this permission notice shall be included in all 31 | copies or substantial portions of the Software. 32 | 33 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 34 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 35 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 36 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 37 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 38 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 39 | SOFTWARE. 40 | -------------------------------------------------------------------------------- /Select Layers by Name.sketchplugin/Contents/Sketch/script.cocoascript: -------------------------------------------------------------------------------- 1 | /** 2 | * Initalize default values 3 | * @param {Object} context — context object supplied by Sketch 4 | * @param {String} userInputHint — instructions for users in the input dialog 5 | */ 6 | 7 | function init(context, userInputHint) { 8 | var doc = context.document; 9 | var initialInputValue = (context.selection.length() > 0) ? context.selection[0].name() : ""; 10 | 11 | this.userInput = doc.askForUserInput_initialValue(userInputHint, initialInputValue); 12 | this.targetName = userInput.toLowerCase(); 13 | this.currentPage = doc.currentPage(); 14 | this.allLayers = currentPage.children(); 15 | 16 | this.currentPage.deselectAllLayers(); 17 | 18 | return this; 19 | } 20 | 21 | /** 22 | * Generate message based on selected elements count 23 | * @param {Object} context — context object supplied by Sketch 24 | * @param {Number} count — number of elements selected 25 | * @param {String} messageNone — message to be returned if no elements were selected 26 | * @param {String} messageSingle — message to be returned if exactly one element was selected 27 | * @param {String} messageMultiple — message to be returned if more then one element was selected 28 | * @returns {String} 29 | */ 30 | 31 | function generateMessage(context, count, messageNone, messageSingle, messageMultiple) { 32 | if (count === 0) { 33 | context.document.showMessage(messageNone); 34 | } else if (count === 1) { 35 | context.document.showMessage(messageSingle); 36 | } else { 37 | context.document.showMessage(messageMultiple); 38 | } 39 | } 40 | 41 | /** 42 | * Check whether the layer is of a class that makes sense selecting 43 | * @param {Object} layer — a Sketch layer 44 | * @returns {Boolean} 45 | */ 46 | 47 | function isSelectable(layer) { 48 | var layerClass = layer.class(); 49 | 50 | if (layerClass == "MSArtboardGroup" || layerClass == "MSBitmapLayer" || layerClass == "MSLayerGroup" || layerClass == "MSShapeGroup" || layerClass == "MSTextLayer") { 51 | return true; 52 | } else { 53 | return false; 54 | } 55 | } 56 | 57 | var matchExact = function(context) { 58 | 59 | var values = init(context, "Select layer(s) by matching name exactly"); 60 | 61 | var count = 0; 62 | var loop = values.allLayers.objectEnumerator(); 63 | while (layer = loop.nextObject()) { 64 | if (isSelectable(layer)){ 65 | if (layer.name().toLowerCase() == values.targetName) { 66 | layer.select_byExpandingSelection(true, true); 67 | count = count + 1; 68 | } 69 | } 70 | } 71 | 72 | var messageNone = "No layers called '" + values.userInput + "' were found :("; 73 | var messageSingle = "Selected 1 layer called '" + values.userInput + "'"; 74 | var messageMultiple = "Selected " + count + " layers called '" + values.userInput + "'"; 75 | 76 | generateMessage(context, count, messageNone, messageSingle, messageMultiple); 77 | 78 | }; 79 | 80 | var matchPartial = function(context) { 81 | 82 | var values = init(context, "Select layer(s) by matching name partially"); 83 | 84 | var count = 0; 85 | var loop = values.allLayers.objectEnumerator(); 86 | while (layer = loop.nextObject()) { 87 | if (isSelectable(layer)){ 88 | layerName = layer.name().toLowerCase(); 89 | if (layerName.indexOf(values.targetName) > -1) { 90 | layer.select_byExpandingSelection(true, true); 91 | count = count + 1; 92 | } 93 | } 94 | } 95 | 96 | var messageNone = "No layers whose name contains '" + userInput + "' were found :("; 97 | var messageSingle = "Selected 1 layer whose name contains '" + userInput + "'"; 98 | var messageMultiple = "Selected " + count + " layers whose name contains '" + userInput + "'"; 99 | 100 | generateMessage(context, count, messageNone, messageSingle, messageMultiple); 101 | }; --------------------------------------------------------------------------------