├── LICENSE ├── README.md ├── index.js └── package.json /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Moises Martinez 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | hyper-tab-touchbar 2 | ====== 3 | 4 | # Use your MacBook Pro's TouchBar to jump to your tabs 5 | 6 | # Install 7 | 8 | From hyper terminal: `hyper i hyper-tab-touchbar` 9 | 10 | # Features: 11 | 12 | - Show your open tabs in your MacBook Pro's TouchBar 13 | - Click on the tabs to jump to the specific tab 14 | - If you have [hyper-folder-icon](https://github.com/moimart/hyper-folder-icon) installed, you can have your Volumes and custom folder's icons shown in the TouchBar 15 | 16 | ![alt text](https://i.imgur.com/2pnvB1w.jpg) 17 | 18 | ## Optional Configuration keys 19 | 20 | - All inside hyperTouchBar object 21 | - activeColor -> hex rgb value string like '#005566' (that's the default value) 22 | - inactiveColor -> hex rgb value string like '#777777' (that's the default value) 23 | - specialButton -> Object containing a script path exporting an arrow function (window) => {} ; By default it 'clears' the active terminal 24 | 25 | ``` 26 | { 27 | activeColor: '#005566', 28 | inactiveColor: '#777777', 29 | specialButton: { 30 | label: 'clear', 31 | onClick: 'path_to_file.js' 32 | } 33 | } 34 | ``` 35 | 36 | The script simply exports a function: 37 | 38 | ``` 39 | module.exports = { 40 | hyperTouchBarOnClick: () => { 41 | console.log('Hello World'); 42 | } 43 | }; 44 | ``` 45 | 46 | set specialButton to undefined if you don't want the special button to be shown 47 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { nativeImage } = require('electron'); 2 | const { TouchBar } = require('electron'); 3 | const { exec } = require('child_process'); 4 | 5 | Array.prototype.diff = function(a) { 6 | return this.filter(function(i) {return a.indexOf(i) < 0;}); 7 | }; 8 | 9 | let config = { 10 | activeColor: '#005566', 11 | inactiveColor: '#777777', 12 | specialButton: { 13 | label: 'clear', 14 | onClick: () => { 15 | window.store.dispatch({ 16 | type: 'SESSION_CLEAR_ACTIVE' 17 | }); 18 | } 19 | } 20 | }; 21 | 22 | if (TouchBar) { 23 | //We are inside the main process 24 | 25 | const { TouchBarButton } = TouchBar; 26 | 27 | exports.onWindow = (window) => { 28 | if (window) { 29 | 30 | window.rpc.on('touchbar-tabs', (tabs) => { 31 | let buttons = []; 32 | 33 | for (let data of tabs) { 34 | if (data.iconData) { 35 | data.icon = nativeImage.createFromBuffer(Buffer.from(data.iconData.buffer,'base64')); 36 | } else { 37 | delete data.icon; 38 | } 39 | 40 | if (!data.specialButton) { 41 | data.click = () => { 42 | window.rpc.emit('activate-tab-uid',data.sessionUid); 43 | }; 44 | } else { 45 | data.click = () => { 46 | window.rpc.emit('activate-tab-special') 47 | } 48 | } 49 | 50 | buttons.push(new TouchBarButton(data)); 51 | } 52 | 53 | window.setTouchBar(new TouchBar(buttons)); 54 | }); 55 | } 56 | } 57 | } 58 | 59 | var allTabs = {}; 60 | var listener; 61 | 62 | let populateTouchBar = () => { 63 | 64 | if (Object.keys(allTabs).length == 1) { 65 | allTabs = {}; 66 | 67 | if (config.specialButton) { 68 | let buttonsData = [{ 69 | label: config.specialButton.label, 70 | specialButton: true, 71 | backgroundColor: config.activeColor 72 | }]; 73 | 74 | window.rpc.emit('touchbar-tabs',buttonsData); 75 | } 76 | 77 | return; 78 | } 79 | 80 | let buttonsData = []; 81 | 82 | if (config.specialButton) { 83 | buttonsData.push({ 84 | label: config.specialButton.label, 85 | specialButton: true, 86 | backgroundColor: config.activeColor 87 | }); 88 | } 89 | 90 | for (let uid of Object.keys(allTabs)) { 91 | buttonsData.push({ 92 | sessionUid: window.store.getState().termGroups.termGroups[uid].sessionUid, 93 | label: allTabs[uid].text, 94 | iconData: (allTabs[uid].iconData) ? allTabs[uid].iconData : undefined, 95 | backgroundColor: allTabs[uid].isActive ? config.activeColor : config.inactiveColor, 96 | iconPosition: "left" 97 | }); 98 | } 99 | 100 | try { 101 | window.rpc.emit('touchbar-tabs',buttonsData); 102 | } catch(error) { 103 | 104 | } 105 | 106 | if (listener == undefined) { 107 | window.rpc.on('activate-tab-uid', (uid) => { 108 | window.store.dispatch({ 109 | type:'SESSION_SET_ACTIVE', 110 | uid 111 | }); 112 | 113 | populateTouchBar(); 114 | }); 115 | 116 | window.rpc.on('activate-tab-special', () => { 117 | if (config.specialButton) { 118 | config.specialButton.onClick(); 119 | } 120 | }); 121 | 122 | listener = window; 123 | } 124 | }; 125 | 126 | exports.getTabProps = (uid,parentProps,props) => { 127 | allTabs[uid.uid] = Object.assign({},allTabs[uid.uid],props); 128 | return props; 129 | } 130 | 131 | exports.getTabsProps = (parentProps,props) => { 132 | const { tabs } = props; 133 | 134 | let existingTabs = {}; 135 | for (let tab of tabs) { 136 | existingTabs[tab.uid] = tab; 137 | } 138 | 139 | let waste = Object.keys(allTabs).slice().diff(Object.keys(existingTabs)); 140 | 141 | for (let w of waste) { 142 | delete allTabs[w]; 143 | } 144 | 145 | populateTouchBar(); 146 | 147 | return props; 148 | } 149 | 150 | exports.middleware = (store) => (next) => (action) => { 151 | const uids = store.getState().sessions.sessions; 152 | 153 | switch (action.type) { 154 | case 'FOLDER_ICON': 155 | if (allTabs.hasOwnProperty(action.icon.uid)) { 156 | allTabs[action.icon.uid].iconData = action.icon.iconData; 157 | populateTouchBar(); 158 | } 159 | break; 160 | 161 | case 'SESSION_SET_ACTIVE': 162 | populateTouchBar(); 163 | break; 164 | 165 | case 'CONFIG_LOAD': 166 | case 'CONFIG_RELOAD': 167 | if (action.config.hyperTouchBar) { 168 | config = Object.assign({},config,action.config.hyperTouchBar); 169 | if (action.config.hyperTouchBar.specialButton 170 | && action.config.hyperTouchBar.specialButton.onClick) { 171 | try { 172 | let fn = require(config.specialButton.onClick).hyperTouchBarOnClick; 173 | if (fn) { 174 | config.specialButton.onClick = fn; 175 | } 176 | } catch (error) { 177 | //do nothing... 178 | } 179 | } 180 | } 181 | break; 182 | } 183 | 184 | next(action); 185 | }; 186 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hyper-tab-touchbar", 3 | "version": "0.0.4", 4 | "description": "Show hyper tabs in the MacBook Pro's TouchBar", 5 | "main": "./index.js", 6 | "author": "Moises Martinez ", 7 | "license": "BSD-2-Clause", 8 | "dependencies": { 9 | }, 10 | "keywords": [ 11 | "hyper", 12 | "touchbar", 13 | "macos" 14 | ], 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/moimart/hyper-tab-touchbar.git" 18 | } 19 | } 20 | --------------------------------------------------------------------------------