Permalink
Browse files

add version 0.1.2

  • Loading branch information...
1 parent 30e9697 commit 4346a055e301ef2807bc4ddd76b1999bad49bf03 @alanhamlett alanhamlett committed Jun 25, 2013
Showing with 395 additions and 3 deletions.
  1. +20 −0 LICENSE.txt
  2. +19 −3 README.md
  3. 0 doc/wakatime.txt
  4. +185 −0 plugin/wakatime.py
  5. +171 −0 plugin/wakatime.vim
View
@@ -0,0 +1,20 @@
+Copyright (c) 2013 Wakatime
+https://wakatime.com
+
+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.
View
@@ -1,4 +1,20 @@
-vim-wakatime
-============
+vim-wakatime 0.1.2
+===========
+
+Automatic time tracking.
+
+Installation
+------------
+
+Get an api key by signing up at https://www.wakati.me
+
+Using [Vundle](https://github.com/gmarik/vundle), the Vim plugin manager:
+
+Add `Bundle 'wakatime/vim-wakatime' to your `~/.vimrc`
+
+Then run these shell commands:
+
+ sudo touch /var/log/wakatime.log
+ echo "api_key=MY_API_KEY" > ~/.wakatime
+ vim +BundleInstall +qall
-automatic time tracking for Vim
View
No changes.
View
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+
+import os
+import sys
+import argparse
+import platform
+import urllib2
+import json
+import base64
+import uuid
+import time
+import re
+from collections import OrderedDict
+from httplib import BadStatusLine, IncompleteRead
+from urllib2 import HTTPError, URLError
+import logging as log
+
+
+# Config
+version = '0.1.2'
+user_agent = 'vim-wakatime/%s (%s)' % (version, platform.platform())
+
+
+def project_from_path(path):
+ project = git_project(path)
+ if project:
+ return project
+ return None
+
+
+def tags_from_path(path):
+ tags = []
+ if os.path.exists(path):
+ tags.extend(git_tags(path))
+ tags.extend(mercurial_tags(path))
+ return list(set(tags))
+
+
+def git_project(path):
+ config_file = find_git_config(path)
+ if config_file:
+ folder = os.path.split(os.path.split(os.path.split(config_file)[0])[0])[1]
+ if folder:
+ return folder
+ return None
+
+
+def find_git_config(path):
+ path = os.path.realpath(path)
+ log.info(path)
+ if os.path.isfile(path):
+ path = os.path.split(path)[0]
+ if os.path.isfile(os.path.join(path, '.git', 'config')):
+ return os.path.join(path, '.git', 'config')
+ split_path = os.path.split(path)
+ if split_path[1] == '':
+ return None
+ return find_git_config(split_path[0])
+
+
+def parse_git_config(config):
+ sections = OrderedDict()
+ try:
+ f = open(config, 'r')
+ except IOError as e:
+ log.exception("Exception:")
+ else:
+ with f:
+ section = None
+ for line in f.readlines():
+ line = line.lstrip()
+ if len(line) > 0 and line[0] == '[':
+ section = line[1:].split(']', 1)[0]
+ temp = section.split(' ', 1)
+ section = temp[0].lower()
+ if len(temp) > 1:
+ section = ' '.join([section, temp[1]])
+ sections[section] = OrderedDict()
+ else:
+ try:
+ (setting, value) = line.split('=', 1)
+ except ValueError:
+ setting = line.split('#', 1)[0].split(';', 1)[0]
+ value = 'true'
+ setting = setting.strip().lower()
+ value = value.split('#', 1)[0].split(';', 1)[0].strip()
+ sections[section][setting] = value
+ f.close()
+ return sections
+
+
+def git_tags(path):
+ tags = []
+ config_file = find_git_config(path)
+ if config_file:
+ sections = parse_git_config(config_file)
+ for section in sections:
+ if section.split(' ', 1)[0] == 'remote' and 'url' in sections[section]:
+ tags.append(sections[section]['url'])
+ return tags
+
+
+def mercurial_tags(path):
+ tags = []
+ return tags
+
+
+def svn_tags(path):
+ tags = []
+ return tags
+
+
+def log_action(**kwargs):
+ kwargs['User-Agent'] = user_agent
+ log.info(json.dumps(kwargs))
+
+
+def send_action(key, instance, action, task, timestamp, project, tags):
+ url = 'https://www.wakati.me/api/v1/actions'
+ data = {
+ 'type': action,
+ 'task': task,
+ 'time': time.time(),
+ 'instance_id': instance,
+ 'project': project,
+ 'tags': tags,
+ }
+ if timestamp:
+ data['time'] = timestamp
+ request = urllib2.Request(url=url, data=json.dumps(data))
+ request.add_header('User-Agent', user_agent)
+ request.add_header('Content-Type', 'application/json')
+ request.add_header('Authorization', 'Basic %s' % base64.b64encode(key))
+ log_action(**data)
+ response = None
+ try:
+ response = urllib2.urlopen(request)
+ except HTTPError as ex:
+ log.error("%s:\ndata=%s\nresponse=%s" % (ex.getcode(), json.dumps(data), ex.read()))
+ if log.getLogger().isEnabledFor(log.DEBUG):
+ log.exception("Exception for %s:\n%s" % (data['time'], json.dumps(data)))
+ except (URLError, IncompleteRead, BadStatusLine) as ex:
+ log.error("%s:\ndata=%s\nmessage=%s" % (ex.__class__.__name__, json.dumps(data), ex))
+ if log.getLogger().isEnabledFor(log.DEBUG):
+ log.exception("Exception for %s:\n%s" % (data['time'], json.dumps(data)))
+ if response:
+ log.debug('response_code=%s response_content=%s' % (response.getcode(), response.read()))
+ if response and (response.getcode() == 200 or response.getcode() == 201):
+ return True
+ return False
+
+
+def parse_args(argv):
+ parser = argparse.ArgumentParser(description='Log time to the wakati.me api')
+ parser.add_argument('--key', dest='key', required=True,
+ help='your wakati.me api key')
+ parser.add_argument('--action', dest='action', required=True,
+ choices=['open_file', 'ping', 'close_file', 'write_file', 'open_editor', 'quit_editor', 'minimize_editor', 'maximize_editor', 'start', 'stop'])
+ parser.add_argument('--task', dest='task', required=True,
+ help='path to file or named task')
+ parser.add_argument('--instance', dest='instance', required=True,
+ help='the UUID4 representing the current editor')
+ parser.add_argument('--time', dest='timestamp', metavar='time', type=float,
+ help='optional floating-point timestamp in seconds')
+ parser.add_argument('--verbose', dest='verbose', action='store_true',
+ help='turns on debug messages in logfile')
+ parser.add_argument('--version', action='version', version=version)
+ return parser.parse_args(argv)
+
+
+def main(argv):
+ args = parse_args(argv)
+ level = log.INFO
+ if args.verbose:
+ level = log.DEBUG
+ del args.verbose
+ log.basicConfig(filename='/var/log/wakatime.log', format='%(asctime)s vim-wakatime/'+version+' %(levelname)s %(message)s', datefmt='%Y-%m-%dT%H:%M:%SZ', level=level)
+ tags = tags_from_path(args.task)
+ project = project_from_path(args.task)
+ send_action(project=project, tags=tags, **vars(args))
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
Oops, something went wrong.

0 comments on commit 4346a05

Please sign in to comment.