Skip to content
Permalink
Browse files

add version 0.1.2

  • Loading branch information...
alanhamlett committed Jun 25, 2013
1 parent 30e9697 commit 4346a055e301ef2807bc4ddd76b1999bad49bf03
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
@@ -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.
@@ -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
No changes.
@@ -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:]))

0 comments on commit 4346a05

Please sign in to comment.
You can’t perform that action at this time.