diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c75c47c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,153 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [Unreleased] +- The ability to open multiple, or same command(s) off one menu item. https://github.com/fitztrev/shuttle/issues/236 +- The ability to add a second json.config file +- The ability to add ```[---]``` in the name of a command to add a line seperator +- Adding a new apple script which will allow running commands in the background with screen +- @philippetev Changes to iTerm applescripts to fix issues with settings in iTerm's Preferences/General +- French translations by @anivon +- @anivon localize Error parsing config message is JSON is invalid +- @blackadmin version typos in about window. +- @ChrisMoriarty add the ability to set the terminal window position and size + +## [1.2.9] - 2016-10-18 +### Added +- @pluwen added Chinese language translations #185 + +### Changed +- All the documentation has been moved out of the readme.md and placed in the wiki. + +### Fixed +- Corrected by @pluwen icon changes changes #184 +- Corrected by @bihicheng config file edits not working #199 + +## [1.2.8] - 2016-10-18 +### Added +- Menus have been translated to Spanish +- Added a bash script to the default JSON file that allows writing a command to terminal without execution #200 + +### Fixed +- Fixed an issue that prevented character escapes #194 +- Fixed an issue that prevented tabs from opening in terminal on macOS #198 +- Fixed an issue where english was not the default language. + +## [1.2.7] - 2016-07-24 +### Added +- Now that iTerm stable is at version 3, the version 2 applescripts no longer apply to the stable branch. shuttle still supports iTerm 2.14. If you still want to use this legacy version you will have to change your iTerm_version setting to legacy. Valid settings are: + +```"iTerm_version": "legacy",``` targeting iTerm 2.14 + +```"iTerm_version": "stable",``` targeting new versions of iTerm + +```"iTerm_version": "nightly",``` targeting only the nightly build of iTerm + +Please make sure to change your shuttle.JSON file accordingly. For more on this see #181 + +### Fixed +- corrected by @mortonfox -- when iTerm startup preferences are set to "Don't Open Any Windows" nothing happens #175. +- corrected by @pluwen shuttle icon contains unwanted artifacts #141 +- Fixed an issue where commas were not getting parsed #173 + +## [1.2.6] - 2016-02-24 +### Added +- added by @keesfransen -- ssh config file parsing only keeps the first alias. This change keeps the menu clean as it only keeps the first argument to Host and will allow for hosts defined like: +``` +Host prod/host host.prod + HostName myserver.local +``` +- Added the script files that compile the applescript files for inclusion in shuttle.app + +### Fixed +- corrected by @mortonfox -- when iTerm stable is running but no windows are open nothing happens. +- iTerm Stable and Terminal apple scripts were not correctly handling events where the app was open but no windows were open. +- Fixed an issue were iTerm Nightly applescripts would not open if a theme was not set. +- Fixed an issue with the URL detection. shuttle checks the command to see if its a URL then opens that URL in the default app. +Example: +``` +"cmd": "cifs://myServer/c$" +``` +Should open the above path in finder. + +## [1.2.5] - 2015-11-05 +### Added +- Added a new feature ```"open_in": "VALUE"``` is a global setting which sets how commands are open. Do they open in new tabs or new windows? This setting accepts the value of ```"tab"``` or ```"new"``` +- Added a new feature ```"default_theme": "VALUE"``` is a global setting which sets the default theme for all terminal windows. +- Cleaned up the default JSON file and changed the names to reflect the action. +- Added alert boxes on errors for ```"iTerm_version": "VALUE"``` and ```"inTerminal": "VALUE"``` + +### Changed +- Changed the readme.md to reflect all options. Please see the new wiki it explains all of the settings. + +## [1.2.4] - 2015-10-17 +### Added +- If ```"title":"Terminal Title"``` is empty then the title becomes the same as the commands menu name. + +### Fixed +- Fixed the icon it was not turning white. +- Fixed iTerm2 variable +- About window on top changes + +## [1.2.3] - 2015-10-15 +### Added +- Applescript Changes allow for iTerm Stable and Nightly support. Note that this only works with Nightly versions starting after 2.9.20150414 +- Open a Command in a new window. In your JSON for the command add this directive: +```"inTerminal": "new",``` +- Open a Command in the existing window. In your JSON for the command add this directive: +```"inTerminal": "current",``` +- Add a Title to your window: In your JSON for the command add this directive: +```"title": "Dev Server - SSH"``` +- Add a Theme to your window: In your JSON for the command add this directive: +```"theme": "Homebrew",``` +- Change the Path to the JSON file. In your home directory create a file called ```~/.shuttle.path``` In this file is the path to the JSON settings. Mine currently reads ```/Users/thshdw/Desktop/shuttle.json``` +- Change the default editor. In the JSON settings change ```“editor”: “default”``` will open the settings file from the Settings > edit menu in that editor. Set the editor to 'nano', 'vi', or any terminal based editor. +- Shuttle About Opens a GUI window that shows the version with a button to the home page. + +## [1.2.2] - 2014-11-01 +### Added +- Adds support for dark mode in Yosemite + +## [1.2.0] - 2013-12-02 +### Added +- Include option to show/hide servers from SSH config files +- Include option to ignore hosts based on name or keyword +- Ability to Import/Export settings file +- Support for multiple nested menus + +### Fixed +- Remove status icon from status bar on quit + +## [1.1.2] - 2013-07-23 +### Fixed +- Fix issue with parsing the default JSON config file + +## [1.1.1] - 2013-07-19 +### Added +- cmd in .shuttle.json now supports URLs (http://, smb://, vnc://, etc.) +Opens in your OS default applications +- Added test configuration files + +### Changed +- Create default config file on application load, instead of menu open + +### Fixed +- Fix issue with iTerm running command in the previous tab's split, instead of the new tab. +- Escape double quote characters in cmd + +## [1.1.0] - 2013-07-16 +### Added +- Option to automatically launch at login +- In addition to the JSON config, also generate menu items from hosts in .ssh/config + +## [1.0.1] - 2013-07-11 +### Added +- OS X 10.7 support +- Change menu bar item to use an icon instead of "SSH". + +## [1.0.0] - 2013-07-10 +### Added +- Initial Release diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7130522 --- /dev/null +++ b/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2013 Trevor Fitzgerald + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index c59f29a..47daeaa 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,23 @@ # Shuttle -A simple SSH shortcut menu for OS X +[![Join the chat at https://gitter.im/fitztrev/shuttle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/fitztrev/shuttle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +A simple shortcut menu for macOS [http://fitztrev.github.io/shuttle/](http://fitztrev.github.io/shuttle/) -![How Shuttle works](https://raw.github.com/fitztrev/shuttle/gh-pages/img/how-shuttle-works.gif) +![How Shuttle works](https://raw.githubusercontent.com/fitztrev/shuttle/gh-pages/images/how-shuttle-works.gif) + +**Sidenote**: *Many people ask, so here's how I have [my terminal setup](https://github.com/fitztrev/shuttle/wiki/My-Terminal-Prompt).* ## Installation 1. Download [Shuttle](http://fitztrev.github.io/shuttle/) 2. Copy to Applications +## Help +See the [Wiki](https://github.com/fitztrev/shuttle/wiki) pages. + ## Roadmap * Cloud hosting integration @@ -22,6 +29,36 @@ A simple SSH shortcut menu for OS X * Open menu * Select host option within menu +## Contributors + +This project was created by [Trevor Fitzgerald](https://github.com/fitztrev). I owe many thanks to the following people who have helped make Shuttle even better. + +(In alphabetical order) + +* [Alexis NIVON](https://github.com/anivon) +* [Alex Carter](https://github.com/blazeworx) +* [bihicheng](https://github.com/bihicheng) +* [Dave Eddy](https://github.com/bahamas10) +* [Dmitry Filimonov](https://github.com/petethepig) +* [Frank Enderle](https://github.com/fenderle) +* [Jack Weeden](https://github.com/jackbot) +* [Justin Swanson](https://github.com/geeksunny) +* [Kees Fransen](https://github.com/keesfransen) +* Marco Aurélio +* [Martin Grund](https://github.com/grundprinzip) +* [Matt Turner](https://github.com/thshdw) +* [Michael Davis](https://github.com/mpdavis) +* [Morton Fox](https://github.com/mortonfox) +* [Pluwen](https://github.com/pluwen) +* Rebecca Dominguez +* [Rui Rodrigues](https://github.com/rmrodrigues) +* [Ryan Cohen](https://github.com/imryan) +* [Stefan Jansen](https://github.com/steffex) +* Thomas Rosenstein +* [Thoro](https://github.com/Thoro) +* [Tibor Bödecs](https://github.com/tib) +* [welsonla](https://github.com/welsonla) + ## Credits Shuttle was inspired by [SSHMenu](http://sshmenu.sourceforge.net/), the GNOME applet for Linux. diff --git a/Shuttle.xcodeproj/project.pbxproj b/Shuttle.xcodeproj/project.pbxproj index 962b1ec..d174fef 100644 --- a/Shuttle.xcodeproj/project.pbxproj +++ b/Shuttle.xcodeproj/project.pbxproj @@ -12,7 +12,20 @@ 0ADB3B0E178EF8DB004E9BB9 /* StatusIcon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0ADB3B0A178EF8DB004E9BB9 /* StatusIcon@2x.png */; }; 0ADB3B0F178EF8DB004E9BB9 /* StatusIconAlt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 0ADB3B0B178EF8DB004E9BB9 /* StatusIconAlt@2x.png */; }; 0ADB3B13178F3DE4004E9BB9 /* LaunchAtLoginController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ADB3B12178F3DE4004E9BB9 /* LaunchAtLoginController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 24399FE6219CD0F700C8658F /* virtual-with-screen.scpt in Resources */ = {isa = PBXBuildFile; fileRef = 24399FE5219CD0F700C8658F /* virtual-with-screen.scpt */; }; + 6FC541A31D45CF7F00A896E3 /* AboutWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6FC541A51D45CF7F00A896E3 /* AboutWindowController.xib */; }; 7E74A7C61789CE2F0079E0D2 /* shuttle.default.json in Resources */ = {isa = PBXBuildFile; fileRef = 7E74A7C51789CE2F0079E0D2 /* shuttle.default.json */; }; + A124BA191D45572B00218F2F /* iTerm2-stable-current-window.scpt in Resources */ = {isa = PBXBuildFile; fileRef = A124BA161D45572B00218F2F /* iTerm2-stable-current-window.scpt */; }; + A124BA1A1D45572B00218F2F /* iTerm2-stable-new-tab-default.scpt in Resources */ = {isa = PBXBuildFile; fileRef = A124BA171D45572B00218F2F /* iTerm2-stable-new-tab-default.scpt */; }; + A124BA1B1D45572B00218F2F /* iTerm2-stable-new-window.scpt in Resources */ = {isa = PBXBuildFile; fileRef = A124BA181D45572B00218F2F /* iTerm2-stable-new-window.scpt */; }; + A12D9BF31BCF2C73004F52A6 /* iTerm2-nightly-current-window.scpt in Resources */ = {isa = PBXBuildFile; fileRef = A12D9BEA1BCF2C73004F52A6 /* iTerm2-nightly-current-window.scpt */; }; + A12D9BF41BCF2C73004F52A6 /* iTerm2-nightly-new-tab-default.scpt in Resources */ = {isa = PBXBuildFile; fileRef = A12D9BEB1BCF2C73004F52A6 /* iTerm2-nightly-new-tab-default.scpt */; }; + A12D9BF51BCF2C73004F52A6 /* iTerm2-nightly-new-window.scpt in Resources */ = {isa = PBXBuildFile; fileRef = A12D9BEC1BCF2C73004F52A6 /* iTerm2-nightly-new-window.scpt */; }; + A12D9BF61BCF2C73004F52A6 /* terminal-current-window.scpt in Resources */ = {isa = PBXBuildFile; fileRef = A12D9BED1BCF2C73004F52A6 /* terminal-current-window.scpt */; }; + A12D9BF71BCF2C73004F52A6 /* terminal-new-tab-default.scpt in Resources */ = {isa = PBXBuildFile; fileRef = A12D9BEE1BCF2C73004F52A6 /* terminal-new-tab-default.scpt */; }; + A12D9BF81BCF2C73004F52A6 /* terminal-new-window.scpt in Resources */ = {isa = PBXBuildFile; fileRef = A12D9BEF1BCF2C73004F52A6 /* terminal-new-window.scpt */; }; + A1B7B9DD1DB53ED200809327 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1B7B9DF1DB53ED200809327 /* Localizable.strings */; }; + A1D700071A5DCE8D003563E4 /* AboutWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = A1D700061A5DCE8D003563E4 /* AboutWindowController.m */; }; C149EBFE15D5214600B1F558 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C149EBFD15D5214600B1F558 /* Cocoa.framework */; }; C149EC0815D5214600B1F558 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C149EC0615D5214600B1F558 /* InfoPlist.strings */; }; C149EC0A15D5214600B1F558 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C149EC0915D5214600B1F558 /* main.m */; }; @@ -29,8 +42,39 @@ 0ADB3B0B178EF8DB004E9BB9 /* StatusIconAlt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "StatusIconAlt@2x.png"; sourceTree = ""; }; 0ADB3B11178F3DE4004E9BB9 /* LaunchAtLoginController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LaunchAtLoginController.h; sourceTree = ""; }; 0ADB3B12178F3DE4004E9BB9 /* LaunchAtLoginController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LaunchAtLoginController.m; sourceTree = ""; }; + 24399FE5219CD0F700C8658F /* virtual-with-screen.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "virtual-with-screen.scpt"; sourceTree = ""; }; 7E72D21E178003ED00A6389C /* Shuttle.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Shuttle.entitlements; sourceTree = ""; }; 7E74A7C51789CE2F0079E0D2 /* shuttle.default.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = shuttle.default.json; sourceTree = ""; }; + A124BA161D45572B00218F2F /* iTerm2-stable-current-window.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iTerm2-stable-current-window.scpt"; sourceTree = ""; }; + A124BA171D45572B00218F2F /* iTerm2-stable-new-tab-default.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iTerm2-stable-new-tab-default.scpt"; sourceTree = ""; }; + A124BA181D45572B00218F2F /* iTerm2-stable-new-window.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iTerm2-stable-new-window.scpt"; sourceTree = ""; }; + A12D9BEA1BCF2C73004F52A6 /* iTerm2-nightly-current-window.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iTerm2-nightly-current-window.scpt"; sourceTree = ""; }; + A12D9BEB1BCF2C73004F52A6 /* iTerm2-nightly-new-tab-default.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iTerm2-nightly-new-tab-default.scpt"; sourceTree = ""; }; + A12D9BEC1BCF2C73004F52A6 /* iTerm2-nightly-new-window.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "iTerm2-nightly-new-window.scpt"; sourceTree = ""; }; + A12D9BED1BCF2C73004F52A6 /* terminal-current-window.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "terminal-current-window.scpt"; sourceTree = ""; }; + A12D9BEE1BCF2C73004F52A6 /* terminal-new-tab-default.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "terminal-new-tab-default.scpt"; sourceTree = ""; }; + A12D9BEF1BCF2C73004F52A6 /* terminal-new-window.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; path = "terminal-new-window.scpt"; sourceTree = ""; }; + A1B7B9D31DB5361700809327 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + A1B7B9DE1DB53ED200809327 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + A1B7B9E01DB53ED700809327 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + A1B7B9E11DB53EDA00809327 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + A1B7B9E21DB5436700809327 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/MainMenu.strings; sourceTree = ""; }; + A1B7B9E41DB5436700809327 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = ""; }; + A1B7B9E51DB5436700809327 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = es; path = es.lproj/Credits.rtf; sourceTree = ""; }; + A1B7B9E61DB5436700809327 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + A1B7B9ED1DB54D6700809327 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/AboutWindowController.xib; sourceTree = ""; }; + A1B7B9EE1DB54D7B00809327 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/MainMenu.strings"; sourceTree = ""; }; + A1B7B9EF1DB54D7F00809327 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/MainMenu.strings; sourceTree = ""; }; + A1B7B9F01DB54D8900809327 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/AboutWindowController.strings; sourceTree = ""; }; + A1B7B9F11DB54D8C00809327 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/AboutWindowController.strings"; sourceTree = ""; }; + A1B7B9F21DB54D9000809327 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/AboutWindowController.strings; sourceTree = ""; }; + A1D700051A5DCDF4003563E4 /* AboutWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AboutWindowController.h; sourceTree = ""; }; + A1D700061A5DCE8D003563E4 /* AboutWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AboutWindowController.m; sourceTree = ""; }; + BDCFF1521E4E890A00B365C9 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/MainMenu.strings; sourceTree = ""; }; + BDCFF1531E4E890A00B365C9 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/AboutWindowController.strings; sourceTree = ""; }; + BDCFF1541E4E890A00B365C9 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = ""; }; + BDCFF1551E4E890A00B365C9 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = fr; path = fr.lproj/Credits.rtf; sourceTree = ""; }; + BDCFF1561E4E890A00B365C9 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; C149EBF915D5214600B1F558 /* Shuttle.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Shuttle.app; sourceTree = BUILT_PRODUCTS_DIR; }; C149EBFD15D5214600B1F558 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; C149EC0015D5214600B1F558 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; @@ -43,7 +87,6 @@ C149EC0D15D5214600B1F558 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; C149EC0F15D5214600B1F558 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; C149EC1015D5214600B1F558 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - C149EC1315D5214600B1F558 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; C159DC2715D5DE7F00F5DE24 /* shuttle.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = shuttle.icns; path = ../shuttle.icns; sourceTree = ""; }; /* End PBXFileReference section */ @@ -70,6 +113,23 @@ name = Images; sourceTree = ""; }; + A12D9BE61BCF2C72004F52A6 /* apple-scpt */ = { + isa = PBXGroup; + children = ( + 24399FE5219CD0F700C8658F /* virtual-with-screen.scpt */, + A124BA161D45572B00218F2F /* iTerm2-stable-current-window.scpt */, + A124BA171D45572B00218F2F /* iTerm2-stable-new-tab-default.scpt */, + A124BA181D45572B00218F2F /* iTerm2-stable-new-window.scpt */, + A12D9BEA1BCF2C73004F52A6 /* iTerm2-nightly-current-window.scpt */, + A12D9BEB1BCF2C73004F52A6 /* iTerm2-nightly-new-tab-default.scpt */, + A12D9BEC1BCF2C73004F52A6 /* iTerm2-nightly-new-window.scpt */, + A12D9BED1BCF2C73004F52A6 /* terminal-current-window.scpt */, + A12D9BEE1BCF2C73004F52A6 /* terminal-new-tab-default.scpt */, + A12D9BEF1BCF2C73004F52A6 /* terminal-new-window.scpt */, + ); + path = "apple-scpt"; + sourceTree = ""; + }; C149EBEE15D5214600B1F558 = { isa = PBXGroup; children = ( @@ -109,6 +169,7 @@ C149EC0315D5214600B1F558 /* Shuttle */ = { isa = PBXGroup; children = ( + A12D9BE61BCF2C72004F52A6 /* apple-scpt */, 7E74A7C51789CE2F0079E0D2 /* shuttle.default.json */, 7E72D21E178003ED00A6389C /* Shuttle.entitlements */, C159DC2715D5DE7F00F5DE24 /* shuttle.icns */, @@ -119,6 +180,9 @@ C149EC1215D5214600B1F558 /* MainMenu.xib */, 0ADB3B10178EF8E2004E9BB9 /* Images */, C149EC0415D5214600B1F558 /* Supporting Files */, + A1D700051A5DCDF4003563E4 /* AboutWindowController.h */, + A1D700061A5DCE8D003563E4 /* AboutWindowController.m */, + 6FC541A51D45CF7F00A896E3 /* AboutWindowController.xib */, ); path = Shuttle; sourceTree = ""; @@ -131,6 +195,7 @@ C149EC0915D5214600B1F558 /* main.m */, C149EC0B15D5214600B1F558 /* Shuttle-Prefix.pch */, C149EC0C15D5214600B1F558 /* Credits.rtf */, + A1B7B9DF1DB53ED200809327 /* Localizable.strings */, ); name = "Supporting Files"; sourceTree = ""; @@ -161,7 +226,7 @@ C149EBF015D5214600B1F558 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0440; + LastUpgradeCheck = 1010; ORGANIZATIONNAME = fitztrev; }; buildConfigurationList = C149EBF315D5214600B1F558 /* Build configuration list for PBXProject "Shuttle" */; @@ -170,6 +235,10 @@ hasScannedForEncodings = 0; knownRegions = ( en, + "zh-Hans", + Base, + es, + fr, ); mainGroup = C149EBEE15D5214600B1F558; productRefGroup = C149EBFA15D5214600B1F558 /* Products */; @@ -186,14 +255,26 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + A12D9BF61BCF2C73004F52A6 /* terminal-current-window.scpt in Resources */, + A12D9BF31BCF2C73004F52A6 /* iTerm2-nightly-current-window.scpt in Resources */, + A1B7B9DD1DB53ED200809327 /* Localizable.strings in Resources */, + A12D9BF51BCF2C73004F52A6 /* iTerm2-nightly-new-window.scpt in Resources */, 0ADB3B0D178EF8DB004E9BB9 /* StatusIcon.png in Resources */, + 24399FE6219CD0F700C8658F /* virtual-with-screen.scpt in Resources */, 0ADB3B0C178EF8DB004E9BB9 /* StatusIconAlt.png in Resources */, C149EC0815D5214600B1F558 /* InfoPlist.strings in Resources */, + 6FC541A31D45CF7F00A896E3 /* AboutWindowController.xib in Resources */, 0ADB3B0F178EF8DB004E9BB9 /* StatusIconAlt@2x.png in Resources */, 0ADB3B0E178EF8DB004E9BB9 /* StatusIcon@2x.png in Resources */, + A124BA191D45572B00218F2F /* iTerm2-stable-current-window.scpt in Resources */, + A12D9BF41BCF2C73004F52A6 /* iTerm2-nightly-new-tab-default.scpt in Resources */, C149EC0E15D5214600B1F558 /* Credits.rtf in Resources */, + A12D9BF71BCF2C73004F52A6 /* terminal-new-tab-default.scpt in Resources */, C149EC1415D5214600B1F558 /* MainMenu.xib in Resources */, + A124BA1B1D45572B00218F2F /* iTerm2-stable-new-window.scpt in Resources */, + A124BA1A1D45572B00218F2F /* iTerm2-stable-new-tab-default.scpt in Resources */, C159DC2815D5DE8000F5DE24 /* shuttle.icns in Resources */, + A12D9BF81BCF2C73004F52A6 /* terminal-new-window.scpt in Resources */, 7E74A7C61789CE2F0079E0D2 /* shuttle.default.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -206,6 +287,7 @@ buildActionMask = 2147483647; files = ( 0ADB3B13178F3DE4004E9BB9 /* LaunchAtLoginController.m in Sources */, + A1D700071A5DCE8D003563E4 /* AboutWindowController.m in Sources */, C149EC0A15D5214600B1F558 /* main.m in Sources */, C149EC1115D5214600B1F558 /* AppDelegate.m in Sources */, ); @@ -214,10 +296,36 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ + 6FC541A51D45CF7F00A896E3 /* AboutWindowController.xib */ = { + isa = PBXVariantGroup; + children = ( + A1B7B9ED1DB54D6700809327 /* Base */, + A1B7B9F01DB54D8900809327 /* en */, + A1B7B9F11DB54D8C00809327 /* zh-Hans */, + A1B7B9F21DB54D9000809327 /* es */, + BDCFF1531E4E890A00B365C9 /* fr */, + ); + name = AboutWindowController.xib; + sourceTree = ""; + }; + A1B7B9DF1DB53ED200809327 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + A1B7B9DE1DB53ED200809327 /* en */, + A1B7B9E01DB53ED700809327 /* Base */, + A1B7B9E11DB53EDA00809327 /* zh-Hans */, + A1B7B9E61DB5436700809327 /* es */, + BDCFF1561E4E890A00B365C9 /* fr */, + ); + name = Localizable.strings; + sourceTree = ""; + }; C149EC0615D5214600B1F558 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( C149EC0715D5214600B1F558 /* en */, + A1B7B9E41DB5436700809327 /* es */, + BDCFF1541E4E890A00B365C9 /* fr */, ); name = InfoPlist.strings; sourceTree = ""; @@ -226,6 +334,8 @@ isa = PBXVariantGroup; children = ( C149EC0D15D5214600B1F558 /* en */, + A1B7B9E51DB5436700809327 /* es */, + BDCFF1551E4E890A00B365C9 /* fr */, ); name = Credits.rtf; sourceTree = ""; @@ -233,7 +343,11 @@ C149EC1215D5214600B1F558 /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( - C149EC1315D5214600B1F558 /* en */, + A1B7B9D31DB5361700809327 /* Base */, + A1B7B9E21DB5436700809327 /* es */, + A1B7B9EE1DB54D7B00809327 /* zh-Hans */, + A1B7B9EF1DB54D7F00809327 /* en */, + BDCFF1521E4E890A00B365C9 /* fr */, ); name = MainMenu.xib; sourceTree = ""; @@ -245,14 +359,33 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -261,7 +394,9 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.8; ONLY_ACTIVE_ARCH = YES; @@ -273,17 +408,37 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.8; SDKROOT = macosx; @@ -299,7 +454,8 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Shuttle/Shuttle-Prefix.pch"; INFOPLIST_FILE = "Shuttle/Shuttle-Info.plist"; - MACOSX_DEPLOYMENT_TARGET = 10.7; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_BUNDLE_IDENTIFIER = "shuttle.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; @@ -314,7 +470,8 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Shuttle/Shuttle-Prefix.pch"; INFOPLIST_FILE = "Shuttle/Shuttle-Info.plist"; - MACOSX_DEPLOYMENT_TARGET = 10.7; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_BUNDLE_IDENTIFIER = "shuttle.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; diff --git a/Shuttle/AboutWindowController.h b/Shuttle/AboutWindowController.h new file mode 100644 index 0000000..4e5fbe5 --- /dev/null +++ b/Shuttle/AboutWindowController.h @@ -0,0 +1,21 @@ +// +// AboutWindowController.h +// Shuttle +// +// Created by Matthew Turner on 1/7/15. +// Copyright (c) 2015 fitztrev. All rights reserved. +// + +#import + +@interface AboutWindowController : NSWindowController + +@property (strong) NSWindowController *aboutWindow; + +@property (strong) IBOutlet NSTextField *appName; +@property (strong) IBOutlet NSTextField *appVersion; +@property (strong) IBOutlet NSTextField *appCopyright; + +- (IBAction)btnHomepage:(id)sender; + +@end diff --git a/Shuttle/AboutWindowController.m b/Shuttle/AboutWindowController.m new file mode 100644 index 0000000..d60d1bc --- /dev/null +++ b/Shuttle/AboutWindowController.m @@ -0,0 +1,79 @@ +// +// AboutWindowController.m +// Shuttle +// +// Created by Matthew Turner on 1/7/15. +// Copyright (c) 2015 fitztrev. All rights reserved. +// + +#import "AboutWindowController.h" + +@interface AboutWindowController () + +@end + +@implementation AboutWindowController +@synthesize aboutWindow; +@synthesize appName; +@synthesize appVersion; +@synthesize appCopyright; + +NSDictionary *plistDict; + +- (id)initWithWindow:(NSWindow *)window +{ + aboutWindow = [super initWithWindow:window]; + if (self) { + // Initialization code here. + } + return self; +} + +- (void)windowDidLoad +{ + [super windowDidLoad]; + //Prevent the window from changing positions after multiple opens. + [aboutWindow setShouldCascadeWindows:NO]; + + //Load the plist so we can get current info for the about box. + plistDict = [[NSBundle mainBundle] infoDictionary]; + + //Get the application name. + id applicationName = [plistDict objectForKey:@"CFBundleName"]; + //Get the build version. + id applicationVersion = [plistDict objectForKey:@"CFBundleVersion"]; + //Get the copyright. + id applicationCopyright = [plistDict objectForKey:@"NSHumanReadableCopyright"]; + + //Build the string for the windows title. + NSString *aboutTitle = [NSString stringWithFormat:@"%@%@", NSLocalizedString(@"About ",nil), applicationName]; + [aboutWindow.window setTitle:aboutTitle]; + + //Build the string for the application name. appName - tagline + NSString *progName = [NSString stringWithFormat:@"%@%@", applicationName, NSLocalizedString(@" - A simple SSH shortcut menu.",nil)]; + [appName setStringValue:progName]; + + //Build the string for the version. Version: $build + NSString *progVersion = [NSString stringWithFormat:@"%@%@", NSLocalizedString(@"Version: ",nil), applicationVersion]; + [appVersion setStringValue:progVersion]; + + //Make the copyright font smaller. + [appCopyright setFont:[NSFont systemFontOfSize:10]]; + [appCopyright setStringValue:applicationCopyright]; + +} + +- (IBAction)btnHomepage:(id)sender { + + //Get the homepage from the plist + id applicationHomepage = [plistDict objectForKey:@"Product Homepage"]; + //Build the homepage's URL. + NSURL *homeURL = [NSURL URLWithString:applicationHomepage]; + + //Go to the website. + [[NSWorkspace sharedWorkspace] openURL:homeURL]; + + //Close the about box. + [aboutWindow close]; +} +@end diff --git a/Shuttle/AppDelegate.h b/Shuttle/AppDelegate.h index db8ec99..5bc763c 100644 --- a/Shuttle/AppDelegate.h +++ b/Shuttle/AppDelegate.h @@ -10,16 +10,39 @@ IBOutlet NSMenu *menu; IBOutlet NSArrayController *arrayController; + NSImage *regularIcon; + NSImage *altIcon; + NSStatusItem *statusItem; NSString *shuttleConfigFile; - // This is for the JSON File + //This is for the JSON File NSDate *configModified; + NSDate *configModified2; NSDate *sshConfigUser; NSDate *sshConfigSystem; - NSString *terminalPref; + //Global settings Pref in the JSON file. + NSString *shuttleJSONPathPref; //Alternate path the JSON file + NSString *shuttleJSONPathAlt; //alternate path to the second JSON file + NSString *shuttleAltConfigFile; //second shuttle JSON file + NSString *terminalPref; //Which terminal will we be using iTerm or Terminal.app + NSString *editorPref; //What app opens the JSON file vi, nano... + NSString *iTermVersionPref; //Which version of iTerm nightly or stable + NSString *openInPref; //By default are commands opened in tabs or new windows. + NSString *themePref; //The global theme. + + BOOL parseAltJSON; //Are we parsing a second JSON file + + //Sort and separator + NSString *menuName; //Menu name after removing the sort [aaa] and separator [---] syntax. + BOOL addSeparator; //Are we adding a separator in the menu. + + //Used to gather ssh config settings NSMutableArray* shuttleHosts; + NSMutableArray* shuttleHostsAlt; + NSMutableArray* ignoreHosts; + NSMutableArray* ignoreKeywords; LaunchAtLoginController *launchAtLoginController; @@ -27,4 +50,4 @@ - (void)menuWillOpen:(NSMenu *)menu; -@end \ No newline at end of file +@end diff --git a/Shuttle/AppDelegate.m b/Shuttle/AppDelegate.m index 607a9e5..2f77935 100644 --- a/Shuttle/AppDelegate.m +++ b/Shuttle/AppDelegate.m @@ -4,25 +4,89 @@ // #import "AppDelegate.h" +#import "AboutWindowController.h" @implementation AppDelegate - (void) awakeFromNib { - // The path for the configuration file (by default: ~/.shuttle.json) - shuttleConfigFile = [NSHomeDirectory() stringByAppendingPathComponent:@".shuttle.json"]; - // Load the menu content - // [self loadMenu]; - + // The location for the JSON path file. This is a simple file that contains the hard path to the *.json settings file. + shuttleJSONPathPref = [NSHomeDirectory() stringByAppendingPathComponent:@".shuttle.path"]; + shuttleJSONPathAlt = [NSHomeDirectory() stringByAppendingPathComponent:@".shuttle-alt.path"]; + + //if file shuttle.path exists in ~/.shuttle.path then read this file as it should contain the custom path to *.json + if( [[NSFileManager defaultManager] fileExistsAtPath:shuttleJSONPathPref] ) { + + //Read the shuttle.path file which contains the path to the json file + NSString *jsonConfigPath = [NSString stringWithContentsOfFile:shuttleJSONPathPref encoding:NSUTF8StringEncoding error:NULL]; + + //Remove the white space if any. + jsonConfigPath = [ jsonConfigPath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + + shuttleConfigFile = jsonConfigPath; + }else{ + // The path for the configuration file (by default: ~/.shuttle.json) + shuttleConfigFile = [NSHomeDirectory() stringByAppendingPathComponent:@".shuttle.json"]; + + // if the config file does not exist, create a default one + if ( ![[NSFileManager defaultManager] fileExistsAtPath:shuttleConfigFile] ) { + NSString *cgFileInResource = [[NSBundle mainBundle] pathForResource:@"shuttle.default" ofType:@"json"]; + [[NSFileManager defaultManager] copyItemAtPath:cgFileInResource toPath:shuttleConfigFile error:nil]; + } + } + + // if the custom alternate json file exists then read the file and use set the output as the alt path. + if ( [[NSFileManager defaultManager] fileExistsAtPath:shuttleJSONPathAlt] ) { + + //Read shuttle-alt.path file which contains the custom path to the alternate json file + NSString *jsonConfigAltPath = [NSString stringWithContentsOfFile:shuttleJSONPathAlt encoding:NSUTF8StringEncoding error:NULL]; + + //Remove whitespace if any + jsonConfigAltPath = [ jsonConfigAltPath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + + //set the global var that contains the alternate path + shuttleAltConfigFile = jsonConfigAltPath; + + //flag the bool for later parsing + parseAltJSON = YES; + }else{ + //the custom alt path does not exist. Assume the default for alt path; if existing flag for later parsing + shuttleAltConfigFile = [NSHomeDirectory() stringByAppendingPathComponent:@".shuttle-alt.json"]; + + if ( [[NSFileManager defaultManager] fileExistsAtPath:shuttleAltConfigFile] ){ + //the default path exists. Flag for later parsing + parseAltJSON = YES; + }else{ + //The user does not want to parse an additional json file. + parseAltJSON = NO; + } + } + + // Define Icons + //only regular icon is needed for 10.10 and higher. OS X changes the icon for us. + regularIcon = [NSImage imageNamed:@"StatusIcon"]; + altIcon = [NSImage imageNamed:@"StatusIconAlt"]; + // Create the status bar item - statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:25.0]; + statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength]; [statusItem setMenu:menu]; - [statusItem setHighlightMode:YES]; - [statusItem setImage:[NSImage imageNamed:@"StatusIcon"]]; - [statusItem setAlternateImage:[NSImage imageNamed:@"StatusIconAlt"]]; - - launchAtLoginController = [[LaunchAtLoginController alloc] init]; + [statusItem setImage: regularIcon]; + + // Check for AppKit Version, add support for darkmode if > 10.9 + BOOL oldAppKitVersion = (floor(NSAppKitVersionNumber) <= 1265); + + // 10.10 or higher, dont load the alt image let OS X style it. + if (!oldAppKitVersion) + { + regularIcon.template = YES; + } + // Load the alt image for OS X < 10.10 + else{ + [statusItem setHighlightMode:YES]; + [statusItem setAlternateImage: altIcon]; + } + launchAtLoginController = [[LaunchAtLoginController alloc] init]; // Needed to trigger the menuWillOpen event [menu setDelegate:self]; } @@ -35,9 +99,7 @@ - (BOOL) needUpdateFor: (NSString*) file with: (NSDate*) old { if (old == NULL) return true; - NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[file stringByExpandingTildeInPath] - error:nil]; - NSDate *date = [attributes fileModificationDate]; + NSDate *date = [self getMTimeFor:file]; return [date compare: old] == NSOrderedDescending; } @@ -50,11 +112,13 @@ - (NSDate*) getMTimeFor: (NSString*) file { - (void)menuWillOpen:(NSMenu *)menu { // Check when the config was last modified if ( [self needUpdateFor:shuttleConfigFile with:configModified] || + [self needUpdateFor:shuttleAltConfigFile with:configModified2] || [self needUpdateFor: @"/etc/ssh/ssh_config" with:sshConfigSystem] || [self needUpdateFor: @"~/.ssh/config" with:sshConfigUser]) { configModified = [self getMTimeFor:shuttleConfigFile]; - sshConfigSystem = [self getMTimeFor: @"/etc/ssh_config"]; + configModified2 = [self getMTimeFor:shuttleAltConfigFile]; + sshConfigSystem = [self getMTimeFor: @"/etc/ssh/ssh_config"]; sshConfigUser = [self getMTimeFor: @"~/.ssh/config"]; [self loadMenu]; @@ -63,7 +127,7 @@ - (void)menuWillOpen:(NSMenu *)menu { // Parsing of the SSH Config File // Courtesy of https://gist.github.com/geeksunny/3376694 -- (NSDictionary*) parseSSHConfigFile { +- (NSDictionary *)parseSSHConfigFile { NSString *configFile = nil; NSFileManager *fileMgr = [[NSFileManager alloc] init]; @@ -82,256 +146,654 @@ - (NSDictionary*) parseSSHConfigFile { // We did not find any config file so we gracefully die return nil; } + return [self parseSSHConfig:configFile]; +} + +- (NSDictionary *)parseSSHConfig:(NSString *)filepath { + // Get file contents into fh. + NSString *fh = [NSString stringWithContentsOfFile:filepath encoding:NSUTF8StringEncoding error:nil]; + // build the regex for matching + NSError* error = NULL; + NSRegularExpression* rx = [NSRegularExpression regularExpressionWithPattern:@"^(#?)[ \\t]*([^ \\t=]+)[ \\t=]+(.*)$" + options:0 + error:&error]; - // Get file contents into fh. - NSString *fh = [NSString stringWithContentsOfFile:configFile encoding:NSUTF8StringEncoding error:nil]; - // Initialize our server list as an empty dictionary variable. - NSMutableDictionary *servers = [NSMutableDictionary dictionaryWithObjects:nil forKeys:nil]; + // create data store + NSMutableDictionary* servers = [[NSMutableDictionary alloc] init]; + NSString* key = nil; // Loop through each line and parse the file. for (NSString *line in [fh componentsSeparatedByString:@"\n"]) { // Strip line - NSString *cleanedLine = [line stringByTrimmingCharactersInSet:[ NSCharacterSet whitespaceCharacterSet]]; + NSString *trimmed = [line stringByTrimmingCharactersInSet:[ NSCharacterSet whitespaceCharacterSet]]; + + // run the regex against the line + NSTextCheckingResult* matches = [rx firstMatchInString:trimmed + options:0 + range:NSMakeRange(0, [trimmed length])]; + if ([matches numberOfRanges] != 4) { + continue; + } + + BOOL isComment = [[trimmed substringWithRange:[matches rangeAtIndex:1]] isEqualToString:@"#"]; + NSString* first = [trimmed substringWithRange:[matches rangeAtIndex:2]]; + NSString* second = [trimmed substringWithRange:[matches rangeAtIndex:3]]; + + // check for special comment key/value pairs + if (isComment && key && [first hasPrefix:@"shuttle."]) { + servers[key][[first substringFromIndex:8]] = second; + } - // Empty lines and lines starting with `#' are comments. - if ([cleanedLine length] == 0 || [line characterAtIndex:0] == '#') + // other comments must be skipped + if (isComment) { continue; + } - // Since there might be the possibility that someone thought it might be useful to use = for separating properties - // we have to check that. And of course for now, we are only looking into the host - // section and gently ignore the rest - NSError* error = NULL; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^Host\\b" options:0 error: &error]; - NSUInteger num = [regex numberOfMatchesInString:cleanedLine options:0 range:NSMakeRange(0, [cleanedLine length])]; - if (num == 1) { + if ([first isEqualToString:@"Include"]) { + // Support for ssh_config Include directive. + NSString *includePath = ([second isAbsolutePath]) + ? [second stringByExpandingTildeInPath] + : [[filepath stringByDeletingLastPathComponent] stringByAppendingPathComponent:second]; - // Somebody really used = - NSArray* components = nil; - if ([cleanedLine rangeOfString:@"="].length != 0) { - components = [cleanedLine componentsSeparatedByString:@"="]; - - } else { - components = [cleanedLine componentsSeparatedByCharactersInSet: - [NSCharacterSet whitespaceCharacterSet]]; - } - NSString* host = [[components objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + [servers addEntriesFromDictionary:[self parseSSHConfig:includePath]]; + } + + if ([first isEqualToString:@"Host"]) { + // a new host section - [servers setObject:[NSDictionary dictionaryWithObject: host forKey:@"Host"] forKey:host] ; + // split multiple aliases on space and only save the first + NSArray* hostAliases = [second componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + hostAliases = [hostAliases filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != ''"]]; + key = [hostAliases firstObject]; + servers[key] = [[NSMutableDictionary alloc] init]; } } - return servers; + return servers; } -// Replaces Underscores with Spaces for better readable names -- (NSString*) humanize: (NSString*) val{ - return [val stringByReplacingOccurrencesOfString:@"_" withString:@" "]; -} - (void) loadMenu { - - // System configuration - NSDictionary* servers = [self parseSSHConfigFile]; - // Clear out the hosts so we can start over NSUInteger n = [[menu itemArray] count]; for (int i=0;i(not recommended)<--\nThis could fail if you have another version of iTerm installed.\n\nPlease fix the JSON settings.\nPress Quit to exit shuttle.",nil); + [self throwError:errorMessage additionalInfo:errorInfo continueOnErrorOption:YES]; + iTermVersionPref = @"stable"; + + }else{ + errorMessage = [NSString stringWithFormat:@"%@%@%@ %@",@"'",iTermVersionPref,@"'", NSLocalizedString(@"is not a valid value for iTerm_version. Please fix this in the JSON file",nil)]; + errorInfo = NSLocalizedString(@"bad \"iTerm_version\": \"VALUE\" in the JSON settings",nil); + [self throwError:errorMessage additionalInfo:errorInfo continueOnErrorOption:NO]; } - [mainItem setSubmenu:submenu]; - [menu insertItem:mainItem atIndex:i]; + } + + if( [iTermVersionPref isEqualToString:@"stable"]) { - } else { - NSMenuItem *menuItem = [menu insertItemWithTitle:key - action:@selector(openHost:) - keyEquivalent:@"" - atIndex:i - ]; - // Save that item's SSH command as its represented object - // so we can call it when it's clicked - [menuItem setRepresentedObject:object]; + //run the applescript that works with iTerm Stable + //if we are running in a new iTerm "Stable" Window + if ( [terminalWindow isEqualToString:@"new"] ) { + [self runScript:iTermStableNewWindow handler:handlerName parameters:passParameters]; + } + //if we are running in the current iTerm "Stable" Window + if ( [terminalWindow isEqualToString:@"current"] ) { + [self runScript:iTermStableCurrentWindow handler:handlerName parameters:passParameters]; + } + //we are using the default action of shuttle... The active window in a new tab + if ( [terminalWindow isEqualToString:@"tab"] ) { + [self runScript:iTermStableNewTabDefault handler:handlerName parameters:passParameters]; + } + //don't spawn a terminal run the command in the background using screen + if ( [terminalWindow isEqualToString:@"virtual"] ) { + [self runScript:terminalVirtualWithScreen handler:handlerName parameters:passParameters]; + } + } + //iTermVersion is not set to "stable" using applescripts Configured for Nightly + if( [iTermVersionPref isEqualToString:@"nightly"]) { + //if we are running in a new iTerm "Nightly" Window + if ( [terminalWindow isEqualToString:@"new"] ) { + [self runScript:iTerm2NightlyNewWindow handler:handlerName parameters:passParameters]; + } + //if we are running in the current iTerm "Nightly" Window + if ( [terminalWindow isEqualToString:@"current"] ) { + [self runScript:iTerm2NightlyCurrentWindow handler:handlerName parameters:passParameters]; + } + //we are using the default action of shuttle... The active window in a new tab + if ( [terminalWindow isEqualToString:@"tab"] ) { + [self runScript:iTerm2NightlyNewTabDefault handler:handlerName parameters:passParameters]; + } + //don't spawn a terminal run the command in the background using screen + if ( [terminalWindow isEqualToString:@"virtual"] ) { + [self runScript:terminalVirtualWithScreen handler:handlerName parameters:passParameters]; + } + } + } + //If JSON settings are set to use Terminal.app + else { + //if we are running in a new terminal Window + if ( [terminalWindow isEqualToString:@"new"] ) { + [self runScript:terminalNewWindow handler:handlerName parameters:passParameters]; + } + //if we are running in the current terminal Window + if ( [terminalWindow isEqualToString:@"current"] ) { + [self runScript:terminalCurrentWindow handler:handlerName parameters:passParameters]; + } + //we are using the default action of shuttle... The active window in a new tab + if ( [terminalWindow isEqualToString:@"tab"] ) { + [self runScript:terminalNewTabDefault handler:handlerName parameters:passParameters]; + } + //don't spawn a terminal run the command in the background using screen + if ( [terminalWindow isEqualToString:@"virtual"] ) { + [self runScript:terminalVirtualWithScreen handler:handlerName parameters:passParameters]; } - i++; } +} + +- (void) runScript:(NSString *)scriptPath handler:(NSString*)handlerName parameters:(NSArray*)parametersInArray { + //special thanks to stackoverflow.com/users/316866/leandro for pointing me the right direction. + //see http://goo.gl/olcpaX + NSAppleScript * appleScript; + NSAppleEventDescriptor * thisApplication, *containerEvent; + NSURL * pathURL = [NSURL fileURLWithPath:scriptPath]; + NSDictionary * appleScriptCreationError = nil; + appleScript = [[NSAppleScript alloc] initWithContentsOfURL:pathURL error:&appleScriptCreationError]; + if (handlerName && [handlerName length]) + { + /* If we have a handlerName (and potentially parameters), we build + * an NSAppleEvent to execute the script. */ + + //Get a descriptor + int pid = [[NSProcessInfo processInfo] processIdentifier]; + thisApplication = [NSAppleEventDescriptor descriptorWithDescriptorType:typeKernelProcessID + bytes:&pid + length:sizeof(pid)]; + + //Create the container event + + //We need these constants from the Carbon OpenScripting framework, but we don't actually need Carbon.framework... +#define kASAppleScriptSuite 'ascr' +#define kASSubroutineEvent 'psbr' +#define keyASSubroutineName 'snam' + containerEvent = [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite + eventID:kASSubroutineEvent + targetDescriptor:thisApplication + returnID:kAutoGenerateReturnID + transactionID:kAnyTransactionID]; + //Set the target handler + [containerEvent setParamDescriptor:[NSAppleEventDescriptor descriptorWithString:handlerName] + forKeyword:keyASSubroutineName]; + + //Pass parameters - parameters is expecting an NSArray with only NSString objects + if ([parametersInArray count]) + { + + NSAppleEventDescriptor *arguments = [[NSAppleEventDescriptor alloc] initListDescriptor]; + NSString *object; + + for (object in parametersInArray) { + [arguments insertDescriptor:[NSAppleEventDescriptor descriptorWithString:object] + atIndex:([arguments numberOfItems] +1)]; + } + + [containerEvent setParamDescriptor:arguments forKeyword:keyDirectObject]; + } + //Execute the event + [appleScript executeAppleEvent:containerEvent error:nil]; + } } -- (void) openHost:(NSMenuItem *) sender { - //NSLog(@"sender: %@", sender); - //NSLog(@"Command: %@",[sender representedObject]); - - if ( [terminalPref isEqualToString: @"iterm"] ) { - NSAppleScript* iTerm2 = [[NSAppleScript alloc] initWithSource: - [NSString stringWithFormat: - @"on ApplicationIsRunning(appName) \n" - @" tell application \"System Events\" to set appNameIsRunning to exists (processes where name is appName) \n" - @" return appNameIsRunning \n" - @"end ApplicationIsRunning \n" - @" \n" - @"set isRunning to ApplicationIsRunning(\"iTerm\") \n" - @" \n" - @"tell application \"iTerm\" \n" - @" tell the current terminal \n" - @" if isRunning then \n" - @" set newSession to (launch session \"Default Session\") \n" - @" tell newSession \n" - @" write text \"clear\" \n" - @" write text \"%1$@\" \n" - @" end tell \n" - @" else \n" - @" tell the current session \n" - @" write text \"clear\" \n" - @" write text \"%1$@\" \n" - @" activate \n" - @" end tell \n" - @" end if \n" - @" end tell \n" - @"end tell \n" - , [sender representedObject]]]; - [iTerm2 executeAndReturnError:nil]; +- (IBAction)showImportPanel:(id)sender { + NSOpenPanel * openPanelObj = [NSOpenPanel openPanel]; + NSInteger tvarNSInteger = [openPanelObj runModal]; + if(tvarNSInteger == NSOKButton){ + //Backup the current configuration + [[NSFileManager defaultManager] moveItemAtPath:shuttleConfigFile toPath: [NSHomeDirectory() stringByAppendingPathComponent:@".shuttle.json.backup"] error: nil]; + + NSURL * selectedFileUrl = [openPanelObj URL]; + //Import the selected file + //NSLog(@"copy filename from %@ to %@",selectedFileUrl.path,shuttleConfigFile); + [[NSFileManager defaultManager] copyItemAtPath:selectedFileUrl.path toPath:shuttleConfigFile error:nil]; + //Delete the old configuration file + [[NSFileManager defaultManager] removeItemAtPath:[NSHomeDirectory() stringByAppendingPathComponent:@".shuttle.json.backup"] error: nil]; } else { - NSAppleScript* terminalapp = [[NSAppleScript alloc] initWithSource: - [NSString stringWithFormat: - @"on ApplicationIsRunning(appName) \n" - @" tell application \"System Events\" to set appNameIsRunning to exists (processes where name is appName) \n" - @" return appNameIsRunning \n" - @"end ApplicationIsRunning \n" - @" \n" - @"set isRunning to ApplicationIsRunning(\"Terminal\") \n" - @" \n" - @"tell application \"Terminal\" \n" - @" if isRunning then \n" - @" activate \n" - @" tell application \"System Events\" to tell process \"Terminal.app\" to keystroke \"t\" using command down \n" - @" do script \"clear\" in front window \n" - @" do script \"%1$@\" in front window \n" - @" else \n" - @" do script \"clear\" in window 1 \n" - @" do script \"%1$@\" in window 1 \n" - @" activate \n" - @" end if \n" - @"end tell \n" - , [sender representedObject]]]; - [terminalapp executeAndReturnError:nil]; + return; + } + +} + +-(void) throwError:(NSString*)errorMessage additionalInfo:(NSString*)errorInfo continueOnErrorOption:(BOOL)continueOption { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setInformativeText:errorInfo]; + [alert setMessageText:errorMessage]; + [alert setAlertStyle:NSWarningAlertStyle]; + + if (continueOption) { + [alert addButtonWithTitle:NSLocalizedString(@"Quit",nil)]; + [alert addButtonWithTitle:NSLocalizedString(@"Continue",nil)]; + + }else{ + [alert addButtonWithTitle:NSLocalizedString(@"Quit",nil)]; + } + + if ([alert runModal] == NSAlertFirstButtonReturn) { + [NSApp terminate:NSApp]; + } +} + +- (IBAction)showExportPanel:(id)sender { + NSSavePanel * savePanelObj = [NSSavePanel savePanel]; + //Display the Save Panel + NSInteger result = [savePanelObj runModal]; + if (result == NSFileHandlingPanelOKButton) { + NSURL *saveURL = [savePanelObj URL]; + // then copy a previous file to the new location + [[NSFileManager defaultManager] copyItemAtPath:shuttleConfigFile toPath:saveURL.path error:nil]; } } - (IBAction)configure:(id)sender { - [[NSWorkspace sharedWorkspace] openFile:shuttleConfigFile]; + + //if the editor setting is omitted or contains 'default' open using the default editor. + if([editorPref rangeOfString:@"default"].location != NSNotFound) { + + [[NSWorkspace sharedWorkspace] openFile:shuttleConfigFile]; + } + else{ + //build the editor command + NSString *editorCommand = [NSString stringWithFormat:@"%@ %@", editorPref, shuttleConfigFile]; + + //build the reprensented object. It's expecting menuCmd, termTheme, termTitle, termWindow, menuName + NSString *editorRepObj = [NSString stringWithFormat:@"%@¬_¬%@¬_¬%@¬_¬%@¬_¬%@", editorCommand, nil, @"Editing shuttle JSON", nil, nil]; + + //make a menu item for the command selector(openHost:) runs in a new terminal window. + NSMenuItem *editorMenu = [[NSMenuItem alloc] initWithTitle:@"editJSONconfig" action:@selector(openHost:) keyEquivalent:(@"")]; + + //set the command for the menu item + [editorMenu setRepresentedObject:editorRepObj]; + + //open the JSON file in the terminal editor. + [self openHost:editorMenu]; + } } - (IBAction)showAbout:(id)sender { - [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString:@"http://fitztrev.github.io/shuttle"]]; + + //Call the windows controller + AboutWindowController *aboutWindow = [[AboutWindowController alloc] initWithWindowNibName:@"AboutWindowController"]; + + //Set the window to stay on top + [aboutWindow.window makeKeyAndOrderFront:nil]; + [aboutWindow.window setLevel:NSFloatingWindowLevel]; + + //Show the window + [aboutWindow showWindow:self]; } - (IBAction)quit:(id)sender { - [NSApp terminate:nil]; + [[NSStatusBar systemStatusBar] removeStatusItem:statusItem]; + [NSApp terminate:NSApp]; } @end diff --git a/Shuttle/Base.lproj/AboutWindowController.xib b/Shuttle/Base.lproj/AboutWindowController.xib new file mode 100644 index 0000000..39437d8 --- /dev/null +++ b/Shuttle/Base.lproj/AboutWindowController.xib @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Shuttle/Base.lproj/Localizable.strings b/Shuttle/Base.lproj/Localizable.strings new file mode 100644 index 0000000..8e9b689 --- /dev/null +++ b/Shuttle/Base.lproj/Localizable.strings @@ -0,0 +1,4 @@ +/* + Localizable.strings + Shuttle +*/ diff --git a/Shuttle/en.lproj/MainMenu.xib b/Shuttle/Base.lproj/MainMenu.xib similarity index 74% rename from Shuttle/en.lproj/MainMenu.xib rename to Shuttle/Base.lproj/MainMenu.xib index c9a6284..b337e50 100644 --- a/Shuttle/en.lproj/MainMenu.xib +++ b/Shuttle/Base.lproj/MainMenu.xib @@ -108,15 +108,42 @@ - + - Configure - + Settings + S 2147483647 - - + submenuAction: + + Settings + + + + Edit + + 2147483647 + + + + + + Export + + 2147483647 + + + + + + Import + + 2147483647 + + + + @@ -150,6 +177,20 @@ YES YES + + Quit + + 2147483647 + + + + + Edit + + 2147483647 + + + @@ -207,15 +248,39 @@ - 642 + 645 + + + + quit: + + + + 650 configure: - + - 643 + 654 + + + + showImportPanel: + + + + 656 + + + + showExportPanel: + + + + 657 @@ -299,10 +364,10 @@ 542 - - + + @@ -312,25 +377,63 @@ - 551 - + 561 + - 543 - + 638 + - 561 - + 644 + - 638 - + 646 + + + + + + 647 + + + + + + + + + + 648 + + + + + 649 + + + + + 651 + + + + + 652 + + + + + 653 + + + @@ -343,20 +446,26 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin - 643 + 657 @@ -367,6 +476,8 @@ id id id + id + id @@ -381,6 +492,14 @@ showAbout: id + + showExportPanel: + id + + + showImportPanel: + id + NSArrayController diff --git a/Shuttle/Shuttle-Info.plist b/Shuttle/Shuttle-Info.plist index ae86995..b760d03 100644 --- a/Shuttle/Shuttle-Info.plist +++ b/Shuttle/Shuttle-Info.plist @@ -3,13 +3,13 @@ CFBundleDevelopmentRegion - en + en_US CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile shuttle CFBundleIdentifier - shuttle.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -17,22 +17,24 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.0 - CFBundleSignature - ???? + 1.3.0 CFBundleVersion - 1.1.0 + 1.3.0 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} LSUIElement + NSAppleEventsUsageDescription + Shuttle needs Automation privileges in Security & Privacy to run applescripts NSHumanReadableCopyright - Copyright © 2013 Trevor Fitzgerald. All rights reserved. + Copyright © 2016 Trevor Fitzgerald. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass NSApplication + Product Homepage + http://fitztrev.github.io/shuttle/ diff --git a/Shuttle/StatusIcon.png b/Shuttle/StatusIcon.png index 9b1f75e..1a563e4 100644 Binary files a/Shuttle/StatusIcon.png and b/Shuttle/StatusIcon.png differ diff --git a/Shuttle/StatusIcon@2x.png b/Shuttle/StatusIcon@2x.png index f7fef90..26f5fe8 100644 Binary files a/Shuttle/StatusIcon@2x.png and b/Shuttle/StatusIcon@2x.png differ diff --git a/Shuttle/StatusIconAlt.png b/Shuttle/StatusIconAlt.png index 613511c..6bb9083 100644 Binary files a/Shuttle/StatusIconAlt.png and b/Shuttle/StatusIconAlt.png differ diff --git a/Shuttle/StatusIconAlt@2x.png b/Shuttle/StatusIconAlt@2x.png index 9cd6415..80fb801 100644 Binary files a/Shuttle/StatusIconAlt@2x.png and b/Shuttle/StatusIconAlt@2x.png differ diff --git a/Shuttle/apple-scpt/iTerm2-nightly-current-window.scpt b/Shuttle/apple-scpt/iTerm2-nightly-current-window.scpt new file mode 100644 index 0000000..25e171e Binary files /dev/null and b/Shuttle/apple-scpt/iTerm2-nightly-current-window.scpt differ diff --git a/Shuttle/apple-scpt/iTerm2-nightly-new-tab-default.scpt b/Shuttle/apple-scpt/iTerm2-nightly-new-tab-default.scpt new file mode 100644 index 0000000..3eec784 Binary files /dev/null and b/Shuttle/apple-scpt/iTerm2-nightly-new-tab-default.scpt differ diff --git a/Shuttle/apple-scpt/iTerm2-nightly-new-window.scpt b/Shuttle/apple-scpt/iTerm2-nightly-new-window.scpt new file mode 100644 index 0000000..d0cbdae Binary files /dev/null and b/Shuttle/apple-scpt/iTerm2-nightly-new-window.scpt differ diff --git a/Shuttle/apple-scpt/iTerm2-stable-current-window.scpt b/Shuttle/apple-scpt/iTerm2-stable-current-window.scpt new file mode 100644 index 0000000..9569524 Binary files /dev/null and b/Shuttle/apple-scpt/iTerm2-stable-current-window.scpt differ diff --git a/Shuttle/apple-scpt/iTerm2-stable-new-tab-default.scpt b/Shuttle/apple-scpt/iTerm2-stable-new-tab-default.scpt new file mode 100644 index 0000000..2aeb57f Binary files /dev/null and b/Shuttle/apple-scpt/iTerm2-stable-new-tab-default.scpt differ diff --git a/Shuttle/apple-scpt/iTerm2-stable-new-window.scpt b/Shuttle/apple-scpt/iTerm2-stable-new-window.scpt new file mode 100644 index 0000000..69b7b05 Binary files /dev/null and b/Shuttle/apple-scpt/iTerm2-stable-new-window.scpt differ diff --git a/Shuttle/apple-scpt/terminal-current-window.scpt b/Shuttle/apple-scpt/terminal-current-window.scpt new file mode 100644 index 0000000..21073d4 Binary files /dev/null and b/Shuttle/apple-scpt/terminal-current-window.scpt differ diff --git a/Shuttle/apple-scpt/terminal-new-tab-default.scpt b/Shuttle/apple-scpt/terminal-new-tab-default.scpt new file mode 100644 index 0000000..926e5eb Binary files /dev/null and b/Shuttle/apple-scpt/terminal-new-tab-default.scpt differ diff --git a/Shuttle/apple-scpt/terminal-new-window.scpt b/Shuttle/apple-scpt/terminal-new-window.scpt new file mode 100644 index 0000000..71eefd5 Binary files /dev/null and b/Shuttle/apple-scpt/terminal-new-window.scpt differ diff --git a/Shuttle/apple-scpt/virtual-with-screen.scpt b/Shuttle/apple-scpt/virtual-with-screen.scpt new file mode 100644 index 0000000..5b666f3 Binary files /dev/null and b/Shuttle/apple-scpt/virtual-with-screen.scpt differ diff --git a/Shuttle/en.lproj/AboutWindowController.strings b/Shuttle/en.lproj/AboutWindowController.strings new file mode 100644 index 0000000..d0b12b4 --- /dev/null +++ b/Shuttle/en.lproj/AboutWindowController.strings @@ -0,0 +1,15 @@ + +/* Class = "NSTextFieldCell"; title = "Version"; ObjectID = "6fl-Xm-UPS"; */ +"6fl-Xm-UPS.title" = "Version"; + +/* Class = "NSTextFieldCell"; title = "Copyright"; ObjectID = "Cmu-CQ-3V9"; */ +"Cmu-CQ-3V9.title" = "Copyright"; + +/* Class = "NSWindow"; title = "Window"; ObjectID = "F0z-JX-Cv5"; */ +"F0z-JX-Cv5.title" = "Window"; + +/* Class = "NSTextFieldCell"; title = "Program Name and Tag Line"; ObjectID = "tb3-eK-HAT"; */ +"tb3-eK-HAT.title" = "Program Name and Tag Line"; + +/* Class = "NSButtonCell"; title = "Homepage"; ObjectID = "uUM-88-32s"; */ +"uUM-88-32s.title" = "Homepage"; diff --git a/Shuttle/en.lproj/Localizable.strings b/Shuttle/en.lproj/Localizable.strings new file mode 100644 index 0000000..56110d4 --- /dev/null +++ b/Shuttle/en.lproj/Localizable.strings @@ -0,0 +1,4 @@ +/* + Localizable.strings + Shuttle + */ diff --git a/Shuttle/en.lproj/MainMenu.strings b/Shuttle/en.lproj/MainMenu.strings new file mode 100644 index 0000000..ca1d48c --- /dev/null +++ b/Shuttle/en.lproj/MainMenu.strings @@ -0,0 +1,42 @@ + +/* Class = "NSMenu"; title = "AMainMenu"; ObjectID = "29"; */ +"29.title" = "AMainMenu"; + +/* Class = "NSMenuItem"; title = "Shuttle"; ObjectID = "56"; */ +"56.title" = "Shuttle"; + +/* Class = "NSMenu"; title = "Shuttle"; ObjectID = "57"; */ +"57.title" = "Shuttle"; + +/* Class = "NSMenuItem"; title = "About Shuttle"; ObjectID = "58"; */ +"58.title" = "About Shuttle"; + +/* Class = "NSMenuItem"; title = "Quit Shuttle"; ObjectID = "136"; */ +"136.title" = "Quit Shuttle"; + +/* Class = "NSMenuItem"; title = "About"; ObjectID = "638"; */ +"638.title" = "About"; + +/* Class = "NSMenuItem"; title = "Quit"; ObjectID = "644"; */ +"644.title" = "Quit"; + +/* Class = "NSMenuItem"; title = "Settings"; ObjectID = "646"; */ +"646.title" = "Settings"; + +/* Class = "NSMenu"; title = "Settings"; ObjectID = "647"; */ +"647.title" = "Settings"; + +/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "648"; */ +"648.title" = "Edit"; + +/* Class = "NSMenuItem"; title = "Quit"; ObjectID = "649"; */ +"649.title" = "Quit"; + +/* Class = "NSMenuItem"; title = "Export"; ObjectID = "651"; */ +"651.title" = "Export"; + +/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "652"; */ +"652.title" = "Edit"; + +/* Class = "NSMenuItem"; title = "Import"; ObjectID = "653"; */ +"653.title" = "Import"; diff --git a/Shuttle/es.lproj/AboutWindowController.strings b/Shuttle/es.lproj/AboutWindowController.strings new file mode 100644 index 0000000..244fc5d --- /dev/null +++ b/Shuttle/es.lproj/AboutWindowController.strings @@ -0,0 +1,18 @@ +/* + Translations done by Rebecca Dominguez + */ + +/* Class = "NSTextFieldCell"; title = "Version"; ObjectID = "6fl-Xm-UPS"; */ +"6fl-Xm-UPS.title" = "Version"; + +/* Class = "NSTextFieldCell"; title = "Copyright"; ObjectID = "Cmu-CQ-3V9"; */ +"Cmu-CQ-3V9.title" = "Copyright"; + +/* Class = "NSWindow"; title = "Window"; ObjectID = "F0z-JX-Cv5"; */ +"F0z-JX-Cv5.title" = "Window"; + +/* Class = "NSTextFieldCell"; title = "Program Name and Tag Line"; ObjectID = "tb3-eK-HAT"; */ +"tb3-eK-HAT.title" = "Program Name and Tag Line"; + +/* Class = "NSButtonCell"; title = "Homepage"; ObjectID = "uUM-88-32s"; */ +"uUM-88-32s.title" = "Página Principal"; diff --git a/Shuttle/es.lproj/Credits.rtf b/Shuttle/es.lproj/Credits.rtf new file mode 100644 index 0000000..46576ef --- /dev/null +++ b/Shuttle/es.lproj/Credits.rtf @@ -0,0 +1,29 @@ +{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw9840\paperh8400 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural + +\f0\b\fs24 \cf0 Engineering: +\b0 \ + Some people\ +\ + +\b Human Interface Design: +\b0 \ + Some other people\ +\ + +\b Testing: +\b0 \ + Hopefully not nobody\ +\ + +\b Documentation: +\b0 \ + Whoever\ +\ + +\b With special thanks to: +\b0 \ + Mom\ +} diff --git a/Shuttle/es.lproj/InfoPlist.strings b/Shuttle/es.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/Shuttle/es.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Shuttle/es.lproj/Localizable.strings b/Shuttle/es.lproj/Localizable.strings new file mode 100644 index 0000000..e91239a --- /dev/null +++ b/Shuttle/es.lproj/Localizable.strings @@ -0,0 +1,9 @@ +/* + Localizable.strings + Shuttle + Translations done by Rebecca Dominguez +*/ + +"About " = "Acerca "; +"Version: " = "Versión: "; +" - A simple SSH shortcut menu." = " - Un SSH menu simple de shortcuts (atajos)."; diff --git a/Shuttle/es.lproj/MainMenu.strings b/Shuttle/es.lproj/MainMenu.strings new file mode 100644 index 0000000..82c76f7 --- /dev/null +++ b/Shuttle/es.lproj/MainMenu.strings @@ -0,0 +1,45 @@ +/* + Translations done by Rebecca Dominguez + */ + +/* Class = "NSMenu"; title = "AMainMenu"; ObjectID = "29"; */ +"29.title" = "AMainMenu"; + +/* Class = "NSMenuItem"; title = "Shuttle"; ObjectID = "56"; */ +"56.title" = "Shuttle"; + +/* Class = "NSMenu"; title = "Shuttle"; ObjectID = "57"; */ +"57.title" = "Shuttle"; + +/* Class = "NSMenuItem"; title = "About Shuttle"; ObjectID = "58"; */ +"58.title" = "Acerca Shuttle"; + +/* Class = "NSMenuItem"; title = "Quit Shuttle"; ObjectID = "136"; */ +"136.title" = "Cerrar Shuttle"; + +/* Class = "NSMenuItem"; title = "About"; ObjectID = "638"; */ +"638.title" = "Acerca"; + +/* Class = "NSMenuItem"; title = "Quit"; ObjectID = "644"; */ +"644.title" = "Cerrar"; + +/* Class = "NSMenuItem"; title = "Settings"; ObjectID = "646"; */ +"646.title" = "Ajustes"; + +/* Class = "NSMenu"; title = "Settings"; ObjectID = "647"; */ +"647.title" = "Ajustes"; + +/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "648"; */ +"648.title" = "Editar"; + +/* Class = "NSMenuItem"; title = "Quit"; ObjectID = "649"; */ +"649.title" = "Cerrar"; + +/* Class = "NSMenuItem"; title = "Export"; ObjectID = "651"; */ +"651.title" = "Exportar"; + +/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "652"; */ +"652.title" = "Editar"; + +/* Class = "NSMenuItem"; title = "Import"; ObjectID = "653"; */ +"653.title" = "Importar"; diff --git a/Shuttle/es.lproj/MainMenu.xib b/Shuttle/es.lproj/MainMenu.xib new file mode 100644 index 0000000..b337e50 --- /dev/null +++ b/Shuttle/es.lproj/MainMenu.xib @@ -0,0 +1,535 @@ + + + + 1080 + 12E55 + 3084 + 1187.39 + 626.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 3084 + + + NSArrayController + NSCustomObject + NSMenu + NSMenuItem + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + AMainMenu + + + + Shuttle + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + Shuttle + + + + About Shuttle + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit Shuttle + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + _NSMainMenu + + + AppDelegate + + + NSFontManager + + + + + + + YES + YES + + + 2147483647 + + + + + + Settings + S + 2147483647 + + + submenuAction: + + Settings + + + + Edit + + 2147483647 + + + + + + Export + + 2147483647 + + + + + + Import + + 2147483647 + + + + + + + + + About + + 2147483647 + + + + + + + + + Quit + + 2147483647 + + + + + YES + + + YES + + YES + YES + YES + YES + YES + + + Quit + + 2147483647 + + + + + Edit + + 2147483647 + + + + + + + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 495 + + + + menu + + + + 558 + + + + arrayController + + + + 621 + + + + showAbout: + + + + 640 + + + + quit: + + + + 645 + + + + quit: + + + + 650 + + + + configure: + + + + 654 + + + + showImportPanel: + + + + 656 + + + + showExportPanel: + + + + 657 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + 56 + + + + + + + + 57 + + + + + + + + + + 58 + + + + + 136 + + + + + 143 + + + + + 420 + + + + + 494 + + + + + 542 + + + + + + + + + + + 620 + + + + + 561 + + + + + 638 + + + + + 644 + + + + + 646 + + + + + + + + 647 + + + + + + + + + + 648 + + + + + 649 + + + + + 651 + + + + + 652 + + + + + 653 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 657 + + + + + AppDelegate + NSObject + + id + id + id + id + id + + + + configure: + id + + + quit: + id + + + showAbout: + id + + + showExportPanel: + id + + + showImportPanel: + id + + + + NSArrayController + NSMenu + + + + arrayController + NSArrayController + + + menu + NSMenu + + + + IBProjectSource + ./Classes/AppDelegate.h + + + + + 0 + IBCocoaFramework + YES + 3 + + {11, 11} + {10, 3} + + YES + + diff --git a/Shuttle/fr.lproj/AboutWindowController.strings b/Shuttle/fr.lproj/AboutWindowController.strings new file mode 100644 index 0000000..836121f --- /dev/null +++ b/Shuttle/fr.lproj/AboutWindowController.strings @@ -0,0 +1,15 @@ + +/* Class = "NSTextFieldCell"; title = "Version"; ObjectID = "6fl-Xm-UPS"; */ +"6fl-Xm-UPS.title" = "Version"; + +/* Class = "NSTextFieldCell"; title = "Copyright"; ObjectID = "Cmu-CQ-3V9"; */ +"Cmu-CQ-3V9.title" = "Copyright"; + +/* Class = "NSWindow"; title = "Window"; ObjectID = "F0z-JX-Cv5"; */ +"F0z-JX-Cv5.title" = "Window"; + +/* Class = "NSTextFieldCell"; title = "Program Name and Tag Line"; ObjectID = "tb3-eK-HAT"; */ +"tb3-eK-HAT.title" = "Program Name and Tag Line"; + +/* Class = "NSButtonCell"; title = "Homepage"; ObjectID = "uUM-88-32s"; */ +"uUM-88-32s.title" = "Page d'accueil"; diff --git a/Shuttle/fr.lproj/Credits.rtf b/Shuttle/fr.lproj/Credits.rtf new file mode 100644 index 0000000..d0744a8 --- /dev/null +++ b/Shuttle/fr.lproj/Credits.rtf @@ -0,0 +1,31 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf810 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +{\*\expandedcolortbl;;} +\paperw11900\paperh16840\vieww9600\viewh8400\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\partightenfactor0 + +\f0\b\fs24 \cf0 Engineering: +\b0 \ + Quelques personnes\ +\ + +\b Human Interface Design: +\b0 \ + Quelques autres personnes\ +\ + +\b Testing: +\b0 \ + Personne, heureusement\ +\ + +\b Documentation: +\b0 \ + Quiconque\ +\ + +\b With special thanks to: +\b0 \ + Maman\ +} \ No newline at end of file diff --git a/Shuttle/fr.lproj/InfoPlist.strings b/Shuttle/fr.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/Shuttle/fr.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Shuttle/fr.lproj/Localizable.strings b/Shuttle/fr.lproj/Localizable.strings new file mode 100644 index 0000000..a6e6f62 --- /dev/null +++ b/Shuttle/fr.lproj/Localizable.strings @@ -0,0 +1,10 @@ +/* + Localizable.strings + Shuttle + Translations done by Alexis NIVON +*/ + +"About " = "A propos de "; +"Version: " = "Version: "; +" - A simple SSH shortcut menu." = " - Le gestionnaire de raccourcis SSH."; +"Error parsing config" = "Fichier de paramétrage invalide"; diff --git a/Shuttle/fr.lproj/MainMenu.strings b/Shuttle/fr.lproj/MainMenu.strings new file mode 100644 index 0000000..d7403c7 --- /dev/null +++ b/Shuttle/fr.lproj/MainMenu.strings @@ -0,0 +1,45 @@ +/* + Translations done by Alexis NIVON + */ + +/* Class = "NSMenu"; title = "AMainMenu"; ObjectID = "29"; */ +"29.title" = "AMainMenu"; + +/* Class = "NSMenuItem"; title = "Shuttle"; ObjectID = "56"; */ +"56.title" = "Shuttle"; + +/* Class = "NSMenu"; title = "Shuttle"; ObjectID = "57"; */ +"57.title" = "Shuttle"; + +/* Class = "NSMenuItem"; title = "About Shuttle"; ObjectID = "58"; */ +"58.title" = "A propos de Shuttle"; + +/* Class = "NSMenuItem"; title = "Quit Shuttle"; ObjectID = "136"; */ +"136.title" = "Quitter Shuttle"; + +/* Class = "NSMenuItem"; title = "About"; ObjectID = "638"; */ +"638.title" = "A propos"; + +/* Class = "NSMenuItem"; title = "Quit"; ObjectID = "644"; */ +"644.title" = "Quitter"; + +/* Class = "NSMenuItem"; title = "Settings"; ObjectID = "646"; */ +"646.title" = "Paramétrage"; + +/* Class = "NSMenu"; title = "Settings"; ObjectID = "647"; */ +"647.title" = "Paramétrage"; + +/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "648"; */ +"648.title" = "Modifier"; + +/* Class = "NSMenuItem"; title = "Quit"; ObjectID = "649"; */ +"649.title" = "Quitter"; + +/* Class = "NSMenuItem"; title = "Export"; ObjectID = "651"; */ +"651.title" = "Exporter"; + +/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "652"; */ +"652.title" = "Modifier"; + +/* Class = "NSMenuItem"; title = "Import"; ObjectID = "653"; */ +"653.title" = "Importer"; diff --git a/Shuttle/shuttle.default.json b/Shuttle/shuttle.default.json index 05d1853..51d1e30 100644 --- a/Shuttle/shuttle.default.json +++ b/Shuttle/shuttle.default.json @@ -1,45 +1,60 @@ { - "_comment": "Valid terminals include: 'Terminal.app' or 'iTerm'", - "_comment": "Hosts will also be read from your ~/.ssh/config or /etc/ssh_config file, if available", - "_comment": "For more information on how to configure, please see http://fitztrev.github.io/shuttle/", - "terminal": "Terminal.app", - "launch_at_login": false, - "hosts": [ - { - "name": "My Dev Server", - "cmd": "ssh username@dev.example.com" - }, - { - "Personal": [ - { - "name": "My blog", - "cmd": "ssh username@blog.example.com" - } - ] - }, - { - "Work": [ - { - "name": "dev.example.net", - "cmd": "ssh username@dev.example.net -p 3000" - }, - { - "name": "staging.example.net", - "cmd": "ssh username@staging.example.net -p 3000" - }, - { - "name": "production.example.net", - "cmd": "ssh username@example.net -p 3000" - } - ] - }, - { - "Vagrant": [ - { - "name": "precise32", - "cmd": "ssh vagrant@127.0.0.1 -p 2222 -i ~/.vagrant.d/insecure_private_key" - } - ] - } - ] + "_comments": [ + "Valid terminals include: 'Terminal.app' or 'iTerm'", + "In the editor value change 'default' to 'nano', 'vi', or another terminal based editor.", + "Hosts will also be read from your ~/.ssh/config or /etc/ssh_config file, if available", + "For more information on how to configure, please see http://fitztrev.github.io/shuttle/" + ], + "editor": "default", + "launch_at_login": false, + "terminal": "Terminal.app", + "iTerm_version": "nightly", + "default_theme": "Homebrew", + "open_in": "new", + "show_ssh_config_hosts": false, + "ssh_config_ignore_hosts": [ ], + "ssh_config_ignore_keywords": [ ], + "hosts": [ + { + "cmd": "ps aux | grep defaults", + "name": "Grep - Opens in Default-window-theme-title" + }, + { + "Spouses Servers": [ + { + "cmd": "echo '—->WARNING! Running commands<-- Are you sure? y/n'; read sure; if [ $sure == y ]; then echo running command && ps aux | grep [a]pple; else echo save to history and show... && history -s 'ps aux | grep [a]pple' && osascript -e 'tell application \"System Events\" to keystroke \"p\" using {control down}'; fi", + "inTerminal": "current", + "name": "Logs - Opens in the current active terminal window" + }, + { + "Jane’s Servers": [ + { + "cmd": "ssh username@blog2.example.com", + "inTerminal": "tab", + "name": "SSH blog - Opens in Tab of active window", + "theme": "basic", + "title": "title of tab" + }, + { + "cmd": "ssh username@shop1.example.com", + "inTerminal": "new", + "name": "SSH Shop - Opens in New Window", + "theme": "basic", + "title": "title of new window" + } + ] + } + ] + }, + { + "Vagrant": [ + { + "cmd": "ssh vagrant@127.0.0.1 -p 2222 -i ~/.vagrant.d/insecure_private_key", + "name": "Vagrant - Opens in default-window-theme-title" + } + ] + } + ] } + + \ No newline at end of file diff --git a/Shuttle/zh-Hans.lproj/AboutWindowController.strings b/Shuttle/zh-Hans.lproj/AboutWindowController.strings new file mode 100644 index 0000000..1ea8a26 --- /dev/null +++ b/Shuttle/zh-Hans.lproj/AboutWindowController.strings @@ -0,0 +1,15 @@ + +/* Class = "NSTextFieldCell"; title = "Version"; ObjectID = "6fl-Xm-UPS"; */ +"6fl-Xm-UPS.title" = "Version"; + +/* Class = "NSTextFieldCell"; title = "Copyright"; ObjectID = "Cmu-CQ-3V9"; */ +"Cmu-CQ-3V9.title" = "Copyright"; + +/* Class = "NSWindow"; title = "Window"; ObjectID = "F0z-JX-Cv5"; */ +"F0z-JX-Cv5.title" = "Window"; + +/* Class = "NSTextFieldCell"; title = "Program Name and Tag Line"; ObjectID = "tb3-eK-HAT"; */ +"tb3-eK-HAT.title" = "Program Name and Tag Line"; + +/* Class = "NSButtonCell"; title = "官方网站"; ObjectID = "uUM-88-32s"; */ +"uUM-88-32s.title" = "官方网站"; diff --git a/Shuttle/zh-Hans.lproj/Localizable.strings b/Shuttle/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000..77499bd --- /dev/null +++ b/Shuttle/zh-Hans.lproj/Localizable.strings @@ -0,0 +1,24 @@ +/* + Localizable.strings + Shuttle + + Created by pluwen on 16/7/25. + Copyright © 2016年 fitztrev. All rights reserved. +*/ +/* NSLocalizedString(@"",nil)*/ + +"About " = "关于 "; +"Version: " = "版本:"; +" - A simple SSH shortcut menu." = " - 简易的 SSH 快捷菜单。"; + +"Quit" = "退出"; +"Continue" = "继续"; + +"is not a valid value for inTerminal. Please fix this in the JSON file" = "不是一个有效的 inTerminal 值。请修改 JSON 文件。"; +"bad \"inTerminal\":\"VALUE\" in the JSON settings" = "错误的 \"inTerminal\":\"VALUE\" 在 JSON 设置中"; + +"\"iTerm_version\": \"VALUE\", is missing.\n\n\"VALUE\" can be:\n\"legacy\" targeting iTerm 2.14\n\"stable\" targeting new versions.\n\"nightly\" targeting nightly builds.\n\nPlease fix your shuttle JSON settings.\nSee readme.md on shuttle's github for help." = "\"iTerm_version\": \"VALUE\", 已丢失。\n\n\"VALUE\" 可以是:\n\"legacy\" 指向 iTerm 2.14\n\"stable\" 指向新版本。\n\"nightly\" 指向内测版本.\n\n请修复你的 Shuttle JSON 设置。\n更多帮助,请浏览 Shuttle 在 GitHub 上的 readme.md 文件。"; +"Press Continue to try iTerm stable applescripts.\n -->(not recommended)<--\nThis will fail if you have another version of iTerm installed.\n\nPlease fix the JSON settings.\nPress Quit to exit shuttle." = "点击“继续”按钮尝试 iTerm 稳定版的 AppleScript。\n -->(不推荐)<--\n如果你有另外一个 iTerm 版本,将会失败。\n\n请修复 JSON 设置。\n点击“退出”按钮退出 Shuttle。"; + +"is not a valid value for iTerm_version. Please fix this in the JSON file" = "不是一个有效的 iTerm_version 值。请修改 JSON 文件。"; +"bad \"iTerm_version\": \"VALUE\" in the JSON settings" = "错误的 \"iTerm_version\": \"VALUE\" 在 JSON 设置中"; \ No newline at end of file diff --git a/Shuttle/zh-Hans.lproj/MainMenu.strings b/Shuttle/zh-Hans.lproj/MainMenu.strings new file mode 100644 index 0000000..2dc991b --- /dev/null +++ b/Shuttle/zh-Hans.lproj/MainMenu.strings @@ -0,0 +1,42 @@ + +/* Class = "NSMenu"; title = "AMainMenu"; ObjectID = "29"; */ +"29.title" = "AMainMenu"; + +/* Class = "NSMenuItem"; title = "Shuttle"; ObjectID = "56"; */ +"56.title" = "Shuttle"; + +/* Class = "NSMenu"; title = "Shuttle"; ObjectID = "57"; */ +"57.title" = "Shuttle"; + +/* Class = "NSMenuItem"; title = "关于 Shuttle"; ObjectID = "58"; */ +"58.title" = "关于 Shuttle"; + +/* Class = "NSMenuItem"; title = "退出 Shuttle"; ObjectID = "136"; */ +"136.title" = "退出 Shuttle"; + +/* Class = "NSMenuItem"; title = "关于"; ObjectID = "638"; */ +"638.title" = "关于"; + +/* Class = "NSMenuItem"; title = "退出"; ObjectID = "644"; */ +"644.title" = "退出"; + +/* Class = "NSMenuItem"; title = "设置"; ObjectID = "646"; */ +"646.title" = "设置"; + +/* Class = "NSMenu"; title = "设置"; ObjectID = "647"; */ +"647.title" = "设置"; + +/* Class = "NSMenuItem"; title = "编辑"; ObjectID = "648"; */ +"648.title" = "编辑"; + +/* Class = "NSMenuItem"; title = "Quit"; ObjectID = "649"; */ +"649.title" = "Quit"; + +/* Class = "NSMenuItem"; title = "导出"; ObjectID = "651"; */ +"651.title" = "导出"; + +/* Class = "NSMenuItem"; title = "Edit"; ObjectID = "652"; */ +"652.title" = "Edit"; + +/* Class = "NSMenuItem"; title = "导入"; ObjectID = "653"; */ +"653.title" = "导入"; diff --git a/apple-scripts/compile-Terminal.sh b/apple-scripts/compile-Terminal.sh new file mode 100755 index 0000000..a33836d --- /dev/null +++ b/apple-scripts/compile-Terminal.sh @@ -0,0 +1,5 @@ +#!/bin/bash +echo "compiling applescripts for OS X terminal..." +osacompile -o ~/Git/shuttle/Shuttle/apple-scpt/terminal-new-window.scpt -x ~/Git/shuttle/apple-scripts/terminal/terminal-new-window.applescript +osacompile -o ~/Git/shuttle/Shuttle/apple-scpt/terminal-current-window.scpt -x ~/Git/shuttle/apple-scripts/terminal/terminal-current-window.applescript +osacompile -o ~/Git/shuttle/Shuttle/apple-scpt/terminal-new-tab-default.scpt -x ~/Git/shuttle/apple-scripts/terminal/terminal-new-tab-default.applescript \ No newline at end of file diff --git a/apple-scripts/compile-Virtual.sh b/apple-scripts/compile-Virtual.sh new file mode 100644 index 0000000..b37f650 --- /dev/null +++ b/apple-scripts/compile-Virtual.sh @@ -0,0 +1,3 @@ +#!/bin/bash +echo "compiling applescripts for OS X virtual..." +osacompile -o ~/Git/shuttle/Shuttle/apple-scpt/virtual-with-screen.scpt -x ~/Git/shuttle/apple-scripts/virtual/virtual-with-screen.applescript \ No newline at end of file diff --git a/apple-scripts/compile-iTermNightly.sh b/apple-scripts/compile-iTermNightly.sh new file mode 100755 index 0000000..a4904f9 --- /dev/null +++ b/apple-scripts/compile-iTermNightly.sh @@ -0,0 +1,5 @@ +#!/bin/bash +echo "compiling applescripts for iTerm Nightly..." +osacompile -o ~/Git/shuttle/Shuttle/apple-scpt/iTerm2-nightly-new-window.scpt -x ~/Git/shuttle/apple-scripts/iTermNightly/iTerm2-nightly-new-window.applescript +osacompile -o ~/Git/shuttle/Shuttle/apple-scpt/iTerm2-nightly-current-window.scpt -x ~/Git/shuttle/apple-scripts/iTermNightly/iTerm2-nightly-current-window.applescript +osacompile -o ~/Git/shuttle/Shuttle/apple-scpt/iTerm2-nightly-new-tab-default.scpt -x ~/Git/shuttle/apple-scripts/iTermNightly/iTerm2-nightly-new-tab-default.applescript \ No newline at end of file diff --git a/apple-scripts/compile-iTermStable.sh b/apple-scripts/compile-iTermStable.sh new file mode 100755 index 0000000..79aef7c --- /dev/null +++ b/apple-scripts/compile-iTermStable.sh @@ -0,0 +1,5 @@ +#!/bin/bash +echo "compiling applescripts for iTerm Stable..." +osacompile -o ~/Git/shuttle/Shuttle/apple-scpt/iTerm2-stable-new-window.scpt -x ~/Git/shuttle/apple-scripts/iTermStable/iTerm2-stable-new-window.applescript +osacompile -o ~/Git/shuttle/Shuttle/apple-scpt/iTerm2-stable-current-window.scpt -x ~/Git/shuttle/apple-scripts/iTermStable/iTerm2-stable-current-window.applescript +osacompile -o ~/Git/shuttle/Shuttle/apple-scpt/iTerm2-stable-new-tab-default.scpt -x ~/Git/shuttle/apple-scripts/iTermStable/iTerm2-stable-new-tab-default.applescript \ No newline at end of file diff --git a/apple-scripts/iTermNightly/iTerm2-nightly-current-window.applescript b/apple-scripts/iTermNightly/iTerm2-nightly-current-window.applescript new file mode 100644 index 0000000..8458376 --- /dev/null +++ b/apple-scripts/iTermNightly/iTerm2-nightly-current-window.applescript @@ -0,0 +1,23 @@ +--for testing uncomment the "on run" block +--on run +-- set argsCmd to "ps aux | grep [s]sh" +-- scriptRun(argsCmd) +--end run + +on scriptRun(argsCmd) + set withCmd to (argsCmd) + CommandRun(withCmd) +end scriptRun + +on CommandRun(withCmd) + tell application "iTerm" + reopen + activate + tell the current window + tell the current session + --set name to theTitle + write text withCmd + end tell + end tell + end tell +end CommandRun diff --git a/apple-scripts/iTermNightly/iTerm2-nightly-new-tab-default.applescript b/apple-scripts/iTermNightly/iTerm2-nightly-new-tab-default.applescript new file mode 100644 index 0000000..1646101 --- /dev/null +++ b/apple-scripts/iTermNightly/iTerm2-nightly-new-tab-default.applescript @@ -0,0 +1,78 @@ +--for testing uncomment the "on run" block +--on run +-- set argsCmd to "ps aux | grep xcode" +-- set argsTheme to "Homebrew" +-- set argsTitle to "Custom title" +-- scriptRun(argsCmd, argsTheme, argsTitle) +--end run + +on scriptRun(argsCmd, argsTheme, argsTitle) + set withCmd to (argsCmd) + set withTheme to (argsTheme) + set theTitle to (argsTitle) + CommandRun(withCmd, withTheme, theTitle) +end scriptRun + +on CommandRun(withCmd, withTheme, theTitle) + tell application "iTerm" + if it is not running then + activate + if (count windows) is 0 then + NewWin(withTheme) of me + end if + SetWinParam(theTitle, withCmd) of me + else if (count windows) is 0 then + NewWin(withTheme) of me + SetWinParam(theTitle, withCmd) of me + else + NewTab(withTheme) of me + SetTabParam(theTitle, withCmd) of me + end if + end tell +end CommandRun + +on NewWin(argsTheme) + tell application "iTerm" + try + create window with profile argsTheme + on error msg + create window with profile "Default" + end try + end tell +end NewWin + +on SetWinParam(argsTitle, argsCmd) + tell application "iTerm" + tell the current window + tell the current session + set name to argsTitle + write text argsCmd + end tell + end tell + end tell +end SetWinParam + +on NewTab(argsTheme) + tell application "iTerm" + tell the current window + try + create tab with profile withTheme + on error msg + create tab with profile "Default" + end try + end tell + end tell +end NewTab + +on SetTabParam(argsTitle, argsCmd) + tell application "iTerm" + tell the current window + tell the current tab + tell the current session + set name to argsTitle + write text argsCmd + end tell + end tell + end tell + end tell +end SetTabParam diff --git a/apple-scripts/iTermNightly/iTerm2-nightly-new-window.applescript b/apple-scripts/iTermNightly/iTerm2-nightly-new-window.applescript new file mode 100644 index 0000000..787cdcb --- /dev/null +++ b/apple-scripts/iTermNightly/iTerm2-nightly-new-window.applescript @@ -0,0 +1,43 @@ +--for testing uncomment the "on run" block +--on run +-- set argsCmd to "ps aux | grep [s]sh" +-- set argsTheme to "Homebrew" +-- set argsTitle to "Custom title" +-- scriptRun(argsCmd, argsTheme, argsTitle) +--end run + +on scriptRun(argsCmd, argsTheme, argsTitle) + set withCmd to (argsCmd) + set withTheme to (argsTheme) + set theTitle to (argsTitle) + CommandRun(withCmd, withTheme, theTitle) +end scriptRun + +on CommandRun(withCmd, withTheme, theTitle) + tell application "iTerm" + if it is not running then + activate + if (count windows) is 0 then + NewWin(withTheme) of me + end if + else + NewWin(withTheme) of me + end if + tell the current window + tell the current session + set name to theTitle + write text withCmd + end tell + end tell + end tell +end CommandRun + +on NewWin(argsTheme) + tell application "iTerm" + try + create window with profile argsTheme + on error msg + create window with profile "Default" + end try + end tell +end NewWin diff --git a/apple-scripts/iTermStable/iTerm2-stable-current-window.applescript b/apple-scripts/iTermStable/iTerm2-stable-current-window.applescript new file mode 100644 index 0000000..9bc5311 --- /dev/null +++ b/apple-scripts/iTermStable/iTerm2-stable-current-window.applescript @@ -0,0 +1,22 @@ +--for testing uncomment the "on run" block +--on run +-- set argsCmd to "ps aux | grep [s]sh" +-- scriptRun(argsCmd) +--end run + +on scriptRun(argsCmd) + set withCmd to (argsCmd) + CommandRun(withCmd) +end scriptRun + +on CommandRun(withCmd) + tell application "iTerm" + reopen + activate + tell the current window + tell the current session + write text withCmd + end tell + end tell + end tell +end CommandRun diff --git a/apple-scripts/iTermStable/iTerm2-stable-new-tab-default.applescript b/apple-scripts/iTermStable/iTerm2-stable-new-tab-default.applescript new file mode 100644 index 0000000..924aae0 --- /dev/null +++ b/apple-scripts/iTermStable/iTerm2-stable-new-tab-default.applescript @@ -0,0 +1,78 @@ +--for testing uncomment the "on run" block +--on run +-- set argsCmd to "ps aux | grep xcode" +-- set argsTheme to "Homebrew" +-- set argsTitle to "Custom title" +-- scriptRun(argsCmd, argsTheme, argsTitle) +--end run + +on scriptRun(argsCmd, argsTheme, argsTitle) + set withCmd to (argsCmd) + set withTheme to (argsTheme) + set theTitle to (argsTitle) + CommandRun(withCmd, withTheme, theTitle) +end scriptRun + +on CommandRun(withCmd, withTheme, theTitle) + tell application "iTerm" + if it is not running then + activate + if (count windows) is 0 then + my NewWin(withTheme) + end if + my SetWinParam(theTitle, withCmd) + else if (count windows) is 0 then + my NewWin(withTheme) + my SetWinParam(theTitle, withCmd) + else + my NewTab(withTheme) + my SetTabParam(theTitle, withCmd) + end if + end tell +end CommandRun + +on NewWin(argsTheme) + tell application "iTerm" + try + create window with profile argsTheme + on error msg + create window with profile "Default" + end try + end tell +end NewWin + +on SetWinParam(argsTitle, argsCmd) + tell application "iTerm" + tell the current window + tell the current session + set name to argsTitle + write text argsCmd + end tell + end tell + end tell +end SetWinParam + +on NewTab(argsTheme) + tell application "iTerm" + tell the current window + try + create tab with profile withTheme + on error msg + create tab with profile "Default" + end try + end tell + end tell +end NewTab + +on SetTabParam(argsTitle, argsCmd) + tell application "iTerm" + tell the current window + tell the current tab + tell the current session + set name to argsTitle + write text argsCmd + end tell + end tell + end tell + end tell +end SetTabParam diff --git a/apple-scripts/iTermStable/iTerm2-stable-new-window.applescript b/apple-scripts/iTermStable/iTerm2-stable-new-window.applescript new file mode 100644 index 0000000..ac036ad --- /dev/null +++ b/apple-scripts/iTermStable/iTerm2-stable-new-window.applescript @@ -0,0 +1,43 @@ +--for testing uncomment the "on run" block +--on run +-- set argsCmd to "ps aux | grep [s]sh" +-- set argsTheme to "Homebrew" +-- set argsTitle to "Custom title" +-- scriptRun(argsCmd, argsTheme, argsTitle) +--end run + +on scriptRun(argsCmd, argsTheme, argsTitle) + set withCmd to (argsCmd) + set withTheme to (argsTheme) + set theTitle to (argsTitle) + CommandRun(withCmd, withTheme, theTitle) +end scriptRun + +on CommandRun(withCmd, withTheme, theTitle) + tell application "iTerm" + if it is not running then + activate + if (count windows) is 0 then + my NewWin(withTheme) + end if + else + my NewWin(withTheme) + end if + tell the current window + tell the current session + set name to theTitle + write text withCmd + end tell + end tell + end tell +end CommandRun + +on NewWin(argsTheme) + tell application "iTerm" + try + create window with profile argsTheme + on error msg + create window with profile "Default" + end try + end tell +end NewWin diff --git a/apple-scripts/iterm2.applescript b/apple-scripts/iterm2.applescript deleted file mode 100644 index f7acb2b..0000000 --- a/apple-scripts/iterm2.applescript +++ /dev/null @@ -1,24 +0,0 @@ -on ApplicationIsRunning(appName) - tell application "System Events" to set appNameIsRunning to exists (processes where name is appName) - return appNameIsRunning -end ApplicationIsRunning - -set isRunning to ApplicationIsRunning("iTerm") - -tell application "iTerm" - tell the current terminal - if isRunning then - set newSession to (launch session "Default Session") - tell newSession - write text "clear" - write text "%1$@" - end tell - else - tell the current session - write text "clear" - write text "%1$@" - activate - end tell - end if - end tell -end tell diff --git a/apple-scripts/terminal.applescript b/apple-scripts/terminal.applescript deleted file mode 100644 index ba61caf..0000000 --- a/apple-scripts/terminal.applescript +++ /dev/null @@ -1,19 +0,0 @@ -on ApplicationIsRunning(appName) - tell application "System Events" to set appNameIsRunning to exists (processes where name is appName) - return appNameIsRunning -end ApplicationIsRunning - -set isRunning to ApplicationIsRunning("Terminal") - -tell application "Terminal" - if isRunning then - activate - tell application "System Events" to tell process "Terminal.app" to keystroke "t" using command down - do script "clear" in front window - do script "%1$@" in front window - else - do script "clear" in window 1 - do script "%1$@" in window 1 - activate - end if -end tell diff --git a/apple-scripts/terminal/terminal-current-window.applescript b/apple-scripts/terminal/terminal-current-window.applescript new file mode 100644 index 0000000..aa15091 --- /dev/null +++ b/apple-scripts/terminal/terminal-current-window.applescript @@ -0,0 +1,18 @@ +--for testing uncomment the "on run" block +--on run +-- set argsCmd to "ps aux | grep [s]sh" +-- scriptRun(argsCmd) +--end run + +on scriptRun(argsCmd) + set withCmd to (argsCmd) + CommandRun(withCmd) +end scriptRun + +on CommandRun(withCmd) + tell application "Terminal" + reopen + activate + do script withCmd in front window + end tell +end CommandRun diff --git a/apple-scripts/terminal/terminal-new-tab-default.applescript b/apple-scripts/terminal/terminal-new-tab-default.applescript new file mode 100644 index 0000000..fe26263 --- /dev/null +++ b/apple-scripts/terminal/terminal-new-tab-default.applescript @@ -0,0 +1,52 @@ +--for testing uncomment the "on run" block +--on run +-- set argsCmd to "ps aux | grep [s]creen" +-- set argsTheme to "Homebrew" +-- set argsTitle to "Custom title" +-- scriptRun(argsCmd, argsTheme, argsTitle) +--end run + +on scriptRun(argsCmd, argsTheme, argsTitle) + set withCmd to (argsCmd) + set withTheme to (argsTheme) + set theTitle to (argsTitle) + CommandRun(withCmd, withTheme, theTitle) +end scriptRun + +on CommandRun(withCmd, withTheme, theTitle) + tell application "Terminal" + if it is not running then + --if this is the first time Terminal is running you have specify window 1 + --if you dont do this you will get two windows and the title wont be set + activate + set newTerm to do script withCmd in window 1 + set newTerm's current settings to settings set withTheme + set custom title of front window to theTitle + else + --Terminal is running get the window count + set windowCount to (count every window) + if windowCount = 0 then + --Terminal is running but no windows are open + --run our script in a new window + reopen + activate + do script withCmd in selected tab of window 1 + else + --Terminal is running and we have a window run in a new tab + reopen + activate + tell application "System Events" + tell process "Terminal" + delay 0.3 + keystroke "t" using {command down} + end tell + end tell + activate + do script withCmd in selected tab of front window + end if + set current settings of selected tab of front window to settings set withTheme + set title displays custom title of front window to true + set custom title of selected tab of front window to theTitle + end if + end tell +end CommandRun \ No newline at end of file diff --git a/apple-scripts/terminal/terminal-new-window.applescript b/apple-scripts/terminal/terminal-new-window.applescript new file mode 100644 index 0000000..f4a090e --- /dev/null +++ b/apple-scripts/terminal/terminal-new-window.applescript @@ -0,0 +1,29 @@ +--for testing uncomment the "on run" block +--on run +-- set argsCmd to "ps aux | grep [s]sh" +-- set argsTheme to "Homebrew" +-- set argsTitle to "Custom title" +-- CommandRun(argsCmd, argsTheme, argsTitle) +--end run + +on scriptRun(argsCmd, argsTheme, argsTitle) + set withCmd to (argsCmd) + set withTheme to (argsTheme) + set theTitle to (argsTitle) + CommandRun(withCmd, withTheme, theTitle) +end scriptRun + +on CommandRun(withCmd, withTheme, theTitle) + tell application "Terminal" + if it is not running then + --if this is the first time Terminal is running you have specify window 1 + --if you dont do this you will get two windows and the title wont be set + set newTerm to do script withCmd in window 1 + else + set newTerm to do script withCmd + end if + activate + set newTerm's current settings to settings set withTheme + set custom title of front window to theTitle + end tell +end CommandRun diff --git a/apple-scripts/virtual/virtual-with-screen.applescript b/apple-scripts/virtual/virtual-with-screen.applescript new file mode 100644 index 0000000..7b2c0dd --- /dev/null +++ b/apple-scripts/virtual/virtual-with-screen.applescript @@ -0,0 +1,17 @@ +--for testing uncomment the "on run" block +--on run +-- set argsCmd to "top" +-- set argsTitle to "Testing Top In Screen" +-- scriptRun(argsCmd, argsTitle) +--end run + +on scriptRun(argsCmd, argsTitle) + set screenSwitches to "screen -d -m -S " + set screenSessionName to "'" & argsTitle & "' " + set withCmd to screenSwitches & screenSessionName & argsCmd + CommandRun(withCmd) +end scriptRun + +on CommandRun(withCmd) + do shell script withCmd +end CommandRun \ No newline at end of file diff --git a/shuttle.icns b/shuttle.icns index 92f01d5..5fbe985 100644 Binary files a/shuttle.icns and b/shuttle.icns differ diff --git a/tests/.shuttle.json b/tests/.shuttle.json new file mode 100644 index 0000000..d970360 --- /dev/null +++ b/tests/.shuttle.json @@ -0,0 +1,59 @@ +{ + "terminal": "Terminal.app", + "launch_at_login": false, + "show_ssh_config_hosts": true, + "hosts": [ + { + "name": "Test escaping characters", + "cmd": "echo \"Hello\"; echo 'world'; " + }, + { + "name": "Test opening URL", + "cmd": "http://fitztrev.github.io/shuttle" + }, + { + "name": "Main Item", + "cmd": "ssh username@dev.example.com" + }, + { + "Submenu 1": [ + { + "name": "Submenu Item #1.1", + "cmd": "ssh username@blog.example.com" + } + ] + }, + { + "Submenu 2": [ + { + "name": "Submenu Item #2.1", + "cmd": "ssh username@dev.example.net -p 3000" + }, + { + "name": "Submenu Item #2.2", + "cmd": "ssh username@staging.example.net -p 3000" + }, + { + "name": "Submenu Item #2.3", + "cmd": "ssh username@example.net -p 3000" + } + ] + }, + { + "Submenu 3": [ + { + "Nested Menu - #3.1": [ + { + "name": "Submenu Item #3.1.1", + "cmd": "echo \"OK\";" + } + ] + }, + { + "name": "Submenu Item #3.2", + "cmd": "ssh vagrant@127.0.0.1 -p 2222 -i ~/.vagrant.d/insecure_private_key" + } + ] + } + ] +} diff --git a/tests/.ssh/config b/tests/.ssh/config new file mode 100644 index 0000000..a1fbeeb --- /dev/null +++ b/tests/.ssh/config @@ -0,0 +1,63 @@ +Include config-includes + +# +# A couple of Github accounts +# Prefixed with `.` so they are ignored from the Shuttle menu +# +Host github.com + User user1 + Hostname github.com + IdentityFile ~/.ssh/github-1.key + +# +# Main menu items +# +Host blog.example.com + User username + Hostname blog.example.com + +# +# Grouped menu items (separated by /) +# +Host Clients/client-a.example.com + User username + Hostname client-a.example.com + +Host Clients/client-b.example.com + User username + Hostname client-b.example.com + +Host Group1/web/web01.example.com + User username + Hostname web01.example.com + +Host Group1/web/web02.example.com + User username + Hostname web02.example.com + +Host Group1/web/web03.example.com + User username + Hostname web03.example.com + +Host Group1/db/mysql01.example.com + User username + Hostname mysql01.example.com + +Host Group1/db/mysql02.example.com + User username + Hostname mysql02.example.com + +# +# Grouped menu items (by Shuttle comment syntax) +# +Host dev01.example.net + # shuttle.name = Work/dev01.example.net (my dev box) + Hostname dev01.example.net + +Host test01.example.net + # shuttle.name = Work/Production/test01.example.net (webserver) + Hostname test01.example.net + +Host test02.example.net + # shuttle.name = Work/Production/test02.example.net (database) + Hostname test02.example.net diff --git a/tests/.ssh/config-includes b/tests/.ssh/config-includes new file mode 100644 index 0000000..fe4e472 --- /dev/null +++ b/tests/.ssh/config-includes @@ -0,0 +1,3 @@ +Host included.example.com + User username + Hostname included.example.com \ No newline at end of file diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..5d11634 --- /dev/null +++ b/tests/README.md @@ -0,0 +1 @@ +Sample config files for testing various functionalities of the application.