Permalink
Browse files

Improved docs

  • Loading branch information...
1 parent 423cb92 commit 887fc5e3d03632fc8a59dfb09bce5dfd9b22aebd Filip Krikava committed Nov 29, 2012
Showing with 162 additions and 121 deletions.
  1. +51 −40 README.md
  2. BIN docs/schreenshot-menu.png
  3. +111 −81 fabfile.py
View
@@ -1,63 +1,74 @@
-<h1><img src="https://github.com/fikovnik/ShiftIt/raw/master/artwork/ShiftIt.png" width="72" height="72" valign="middle"/>ShiftIt </h1>
+<h1><img src="https://github.com/fikovnik/ShiftIt/raw/master/artwork/ShiftIt.png" width="72" height="72" valign="middle"/>ShiftIt</h1>
*Managing window size and position in OSX*
-**Note: The master branch is highly outdated, please have a look at the `shiftit16` branch.**
-
-About
---------
+# About
ShiftIt is an application for OSX that allows you to quickly manipulate window position and size using keyboard shortcuts. It intends to become a full featured window organizer for OSX.
-It is a fork from the original [ShiftIt][1] by [Aravindkumar Rajendiran][2] which is not longer under development. For discussing any sort of stuff about this app, please create a new issue [right here][3] in github. There is also quite a quiet [google group][4], but it's better to post stuff directly here.
+It is a complete rewrite of the original [ShiftIt][1] by [Aravindkumar Rajendiran][2] which is not longer under development. For discussing any sort of stuff about this app, please create a new issue [right here][3].
License: [GNU General Public License v3][5]
-Requirements
-------------
+Change logs: change logs are versioned in the [repository](https://github.com/fikovnik/ShiftIt/tree/develop/release) as well.
+
+## User guide
+
+ShiftIt installs itself in the menu bar (optionally it can be completely hidden). It provides a set of actions that manipulates windows positions and sizes. Following is the current list of actions available.
+
+<img src="https://github.com/fikovnik/ShiftIt/raw/master/docs/screenshot-menu.png" />
+
+Normally, all Cocoa windows and X11 windows are supported.
+
+## Requirements
+
+* OSX 10.6+, 64-bit
+
+The primary development is done on OSX 10.7 Lion, but it should be running under OSX 10.6 Snow Leopard as well.
+
+## FAQ
+
+* **I disabled the `Show Icon in Menu Bar` in the preferences, how can I get it back?**
+
+ Launch the application again. It will open the preference dialog.
+
+* **I pressed a shortcut, but nothing has happened, why?**
+
+ While most of application windows should work well with ShiftIt, there are some exceptions (like the GTK+ OSX applications). If you find any problem, please raise an issue.
+
+* **I pressed a shortcut, something happened, but not what I expected, why?**
+
+ ShiftIt is based on a Cocoa Accessibility API and sometimes this API can be a bit [fragile](http://lists.apple.com/archives/accessibility-dev/2011/Aug/msg00031.html) and not do exactly what it should. In order to help to improve ShiftIt, please submit an issue every time you find some weird behavior. Thanks!
-The primary development is done on OSX 10.6 Snow Leopard, but it should be running under OSX 10.5 Leopard as well.
+## Development
-Compiling
----------
+The repository is based on the git flow model. The development therefore happens in the `develop` branch. Any contribution is welcomed!
-After cloning or download a snapshot of the repository (*master branch
-is recommended*):
+### Local build
- * on OSX 10.6 Snow Leopard
- 1. Compile in XCode by clicking build, or use the
- `scripts/release.sh` (*With the script option, please ignore any errors related to the signing the release. Just check if you see the `** BUILD SUCCEEDED **` message in the output and grab the app from `ShiftIt/build/Release/ShiftIt.app` directory.*)
- 1. That's it
- * on OSX 10.5 Leopard
- 1. Go to `Project` menu and click `Edit Project Settings` item
- 1. Select `Build` tab
- 1. Set `Architectures` to be `32-bit Universal`
- 1. Select `C/C++ Compiler Version` to be `GCC 4.2`
- 1. Check `Build Active Architecture Only`
-
-The reason for this is that the Interface Builder frameworks on OS X Leopard 10.5 do not have 64-Bit capabilities.
+To build ShiftIt locally just clone the repository or get the latest snapshot and execute following command in the `ShiftIt` directory:
-Note: If you have a problem with the build - xcode complaining about the ShortcutRecorder IB plugin then download (from [here][7]) and build it yourself. Once done load it into the Interface Builder (double click on the just built ShortcutRecorder.ibplugin).
+ xcodebuild -target ShiftIt -configuration Release
-FAQ
----
+### Making a release
-**I disabled the `Show Icon in Menu Bar` in the preferences, how can I get it back?how can I get it back?**
+Releases are handled using [frabric](http://docs.fabfile.org/en/1.5/). There are some dependencies that can be easily obtained using `pip`:
-Launch the application again. It will open the preference dialog.
+* [fabric](http://docs.fabfile.org/en/1.5/) - the build system itself
+* [github3](https://github.com/sigmavirus24/github3.py) - library for GitHub 3 API
+* [pystache](https://github.com/defunkt/pystache) - templates
-3rd Party Frameworks
---------------------
+The releases are fully automatic which hopefully will help to release more often.
- * [ShortcutRecorder][7] framework (*New BSD license*) for capturing key bindings during hotkey reconfiguration. (*from version 1.4*)
- * [FMT][8] framework (*MIT license*) for some utility functions like handling login items, hot keys, etc. (*from version 1.5*)
+**Available commands**
-Change Log:
----------------------------
+* `archive` - Archives build
+* `build` - Makes a build by executing xcodebuild
+* `info` - Output all the build properties
+* `prepare_release` - Prepare the release: sign the build, generate appcast, generate release notes, commit and push.
+* `print_release_notes` - Prints release notes
+* `release` - Makes the complete release (same as prepare_release, upload_release)
+* `upload_release` - Uploads the release to github
- - [1.5][9]
- - [1.4.1][10]
- - [1.4][11]
- - [1.3][12]
[1]: http://code.google.com/p/shiftit/
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
@@ -9,9 +9,10 @@
import base64
import datetime
-##
-# Configuration
-##
+################################################################################
+## Configuration
+################################################################################
+
proj_name = 'ShiftIt'
proj_info_plist = 'ShiftIt-Info.plist'
proj_src_dir = 'ShiftIt'
@@ -63,12 +64,22 @@
</rss>
'''.strip()
-##
-# Code
-##
+
+################################################################################
+## Prerequisites
+################################################################################
+
+# if not local('git diff-index --quiet HEAD --').return_code:
+# abort('There are pending changes in the repository. Run git status')
+
+
+################################################################################
+## Code
+################################################################################
def _find(f, seq):
"""Return first item in sequence where f(item) == True."""
+
for item in seq:
if f(item):
return item
@@ -81,28 +92,66 @@ def _get_git_branch():
branch = local('git symbolic-ref HEAD', capture=True)
return branch[len('refs/heads/'):].strip()
-def _sign(path, private_key, public_key):
- sign_file = tempfile.mktemp()
+def _gen_release_notes():
+ def _convert(i):
+ return { \
+ 'number': i.number, \
+ 'html_url': i.html_url, \
+ 'title': i.title, \
+ }
- local('openssl dgst -sha1 -binary < %s | openssl dgst -dss1 -sign %s > %s'
- % (path, private_key, sign_file))
- local('openssl dgst -sha1 -binary < %s | openssl dgst -dss1 -verify %s -signature %s'
- % (path, public_key, sign_file))
+ github = _github()
+ shiftit = github.repository('fikovnik','ShiftIt')
- signature = None
- with open(sign_file) as f:
- signature = base64.b64encode(f.read())
+ milestone = _find(lambda m: proj_version.startswith(m.title), shiftit.iter_milestones())
+ if not milestone:
+ raise Exception('Unable to find milestone: %s' % proj_version)
- os.remove(sign_file)
- return signature
+ open_issues = list(shiftit.iter_issues(milestone=milestone.number, state='open'))
+ if len(open_issues) > 0 and not proj_is_dev:
+ puts('Warning: there are still open issues')
+ for i in open_issues:
+ print '\t * #%s: %s' % (i.number, i.title)
-## check if we are clean
+ closed_issues = list(shiftit.iter_issues(milestone=milestone.number, state='closed'))
+ closed_issues.sort(key=lambda i: i.closed_at)
+
+ release_notes = dict( \
+ has_issues = len(closed_issues) > 0, \
+ issues = closed_issues, \
+ proj_name=proj_name, \
+ proj_version=proj_version, \
+ devel=proj_is_dev, \
+ milestone_url='https://github.com/fikovnik/ShiftIt/issues?milestone=%d' % milestone.number, \
+ )
+
+ puts('Release notes properties:')
+ for (k,v) in release_notes.items():
+ print "\t%s: %s" % (k,v)
+
+ return pystache.render(release_notes_template, release_notes)
+
+def _github():
+ return github3.login(_keychain_get_username('github.com'),
+ _keychain_get_password('github.com'))
+
+
+def _keychain_get_username(account):
+ username = local("security find-internet-password -l %s | grep 'acct' | " \
+ "cut -d '\"' -f 4" % account, capture=True)
+ return username
+
+def _keychain_get_password(account):
+ password = local("security 2>&1 > /dev/null find-internet-password -g -l" \
+ " %s | cut -d '\"' -f 2" % account, capture=True)
+ return password
-# if not local('git diff-index --quiet HEAD --').return_code:
-# abort('There are pending changes in the repository. Run git status')
-## settings
+################################################################################
+## Project settings
+################################################################################
+
proj_branch = _get_git_branch()
proj_is_dev = not proj_branch.startswith('release')
proj_src_dir = os.path.join(os.getcwd(), proj_src_dir)
@@ -122,8 +171,17 @@ def _sign(path, private_key, public_key):
proj_appcast_url = 'https://raw.github.com/fikovnik/ShiftIt/'+proj_branch+'/release/appcast.xml'
proj_appcast_file = os.path.join(os.getcwd(),'release','appcast.xml')
+
+################################################################################
+## Tasks
+################################################################################
+
@task
def info():
+ '''
+ Output all the build properties
+ '''
+
print 'Build info:'
for (k,v) in [(k,v) for (k,v) in globals().items() if k.startswith('proj_')]:
print "\t%s: %s" % (k[len('proj_'):],v)
@@ -150,20 +208,36 @@ def archive():
@task
def prepare_release():
- # prerequisites
+ '''
+ Prepare the release: sign the build, generate appcast, generate release notes, commit and push.
+ '''
- # the appcast URL matches
+ # prerequisites
+ puts('Verify that the update URL matches')
tree = ElementTree.parse(proj_info_plist)
root = tree.getroot().find('dict')
elem = list(root.findall('*'))
-
plist_appcast_url = _find(lambda (k,v): k.text == 'SUFeedURL', zip(*[iter(elem)]*2))[1].text.strip()
if plist_appcast_url != proj_appcast_url:
abort('Appcasts are different! Expected: `%s`, got: `%s`' % (proj_appcast_url, plist_appcast_url))
# dependencies
execute(archive)
+ puts('Sign the build')
+ sign_file = tempfile.mktemp()
+ local('openssl dgst -sha1 -binary < %s | openssl dgst -dss1 -sign %s > %s'
+ % (proj_archive_path, proj_private_key, sign_file))
+ local('openssl dgst -sha1 -binary < %s | openssl dgst -dss1 -verify %s -signature %s'
+ % (proj_archive_path, proj_public_key, sign_file))
+
+ signature = None
+ with open(sign_file) as f:
+ signature = base64.b64encode(f.read())
+
+ os.remove(sign_file)
+
+ # appcast properties
appcast = dict( \
proj_name=proj_name, \
proj_appcast_url=proj_appcast_url, \
@@ -172,7 +246,7 @@ def prepare_release():
date=datetime.datetime.now().strftime('%a, %d %b %G %T %z'), \
download_url=proj_download_url, \
download_size=os.path.getsize(proj_archive_path), \
- download_signature=_sign(proj_archive_path, proj_private_key, proj_public_key), \
+ download_signature=signature, \
)
puts('Appcast properties:')
@@ -199,10 +273,13 @@ def prepare_release():
@task
def upload_release():
+ '''
+ Uploads the release to github
+ '''
+
# dependencies
execute(archive)
-
if not confirm('Proceed with upload?'):
return
@@ -227,66 +304,19 @@ def upload_release():
@task
def release():
+ '''
+ Makes the complete release (same as prepare_release, upload_release)
+ '''
+
# dependencies
execute(prepare_release)
execute(upload_release)
@task
def print_release_notes():
- puts(_gen_release_notes())
-
-def _gen_release_notes():
- def _convert(i):
- return { \
- 'number': i.number, \
- 'html_url': i.html_url, \
- 'title': i.title, \
- }
-
- github = _github()
- shiftit = github.repository('fikovnik','ShiftIt')
-
- milestone = _find(lambda m: proj_version.startswith(m.title), shiftit.iter_milestones())
- if not milestone:
- raise Exception('Unable to find milestone: %s' % proj_version)
-
-
- open_issues = list(shiftit.iter_issues(milestone=milestone.number, state='open'))
- if len(open_issues) > 0 and not proj_is_dev:
- puts('Warning: there are still open issues')
- for i in open_issues:
- print '\t * #%s: %s' % (i.number, i.title)
-
- closed_issues = list(shiftit.iter_issues(milestone=milestone.number, state='closed'))
- closed_issues.sort(key=lambda i: i.closed_at)
-
- release_notes = dict( \
- has_issues = len(closed_issues) > 0, \
- issues = closed_issues, \
- proj_name=proj_name, \
- proj_version=proj_version, \
- devel=proj_is_dev, \
- milestone_url='https://github.com/fikovnik/ShiftIt/issues?milestone=%d' % milestone.number, \
- )
-
- puts('Release notes properties:')
- for (k,v) in release_notes.items():
- print "\t%s: %s" % (k,v)
-
- return pystache.render(release_notes_template, release_notes)
-
-def _github():
- return github3.login(_keychain_get_username('github.com'),
- _keychain_get_password('github.com'))
-
-
-def _keychain_get_username(account):
- username = local("security find-internet-password -l %s | grep 'acct' | " \
- "cut -d '\"' -f 4" % account, capture=True)
- return username
+ '''
+ Prints release notes
+ '''
-def _keychain_get_password(account):
- password = local("security 2>&1 > /dev/null find-internet-password -g -l" \
- " %s | cut -d '\"' -f 2" % account, capture=True)
- return password
+ puts(_gen_release_notes())

0 comments on commit 887fc5e

Please sign in to comment.