mirror of
https://github.com/wakatime/sublime-wakatime.git
synced 2023-08-10 21:13:02 +03:00
show today coding activity time in status bar
This commit is contained in:
parent
d8c662f3db
commit
aa7962d49a
68
WakaTime.py
68
WakaTime.py
@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
""" ==========================================================
|
""" ==========================================================
|
||||||
File: WakaTime.py
|
File: WakaTime.py
|
||||||
Description: Automatic time tracking for Sublime Text 2 and 3.
|
Description: Automatic time tracking for Sublime Text 2 and 3.
|
||||||
@ -25,7 +26,7 @@ import threading
|
|||||||
import traceback
|
import traceback
|
||||||
import urllib
|
import urllib
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from datetime import datetime
|
from contextlib import closing
|
||||||
from subprocess import STDOUT, PIPE
|
from subprocess import STDOUT, PIPE
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
try:
|
try:
|
||||||
@ -40,6 +41,11 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
import queue # py3
|
import queue # py3
|
||||||
|
|
||||||
|
try:
|
||||||
|
import urllib2
|
||||||
|
except ImportError:
|
||||||
|
import urllib.request as urllib2
|
||||||
|
|
||||||
|
|
||||||
is_py2 = (sys.version_info[0] == 2)
|
is_py2 = (sys.version_info[0] == 2)
|
||||||
is_py3 = (sys.version_info[0] == 3)
|
is_py3 = (sys.version_info[0] == 3)
|
||||||
@ -47,6 +53,8 @@ is_win = platform.system() == 'Windows'
|
|||||||
|
|
||||||
|
|
||||||
if is_py2:
|
if is_py2:
|
||||||
|
STATUS_BAR_PREFIX = 'WakaTime'
|
||||||
|
|
||||||
def u(text):
|
def u(text):
|
||||||
if text is None:
|
if text is None:
|
||||||
return None
|
return None
|
||||||
@ -70,6 +78,8 @@ if is_py2:
|
|||||||
return unicode('')
|
return unicode('')
|
||||||
|
|
||||||
elif is_py3:
|
elif is_py3:
|
||||||
|
STATUS_BAR_PREFIX = '🕘'
|
||||||
|
|
||||||
def u(text):
|
def u(text):
|
||||||
if text is None:
|
if text is None:
|
||||||
return None
|
return None
|
||||||
@ -121,6 +131,9 @@ LAST_HEARTBEAT = {
|
|||||||
'is_write': False,
|
'is_write': False,
|
||||||
}
|
}
|
||||||
LAST_HEARTBEAT_SENT_AT = 0
|
LAST_HEARTBEAT_SENT_AT = 0
|
||||||
|
LAST_FETCH_TODAY_CODING_TIME = 0
|
||||||
|
FETCH_TODAY_DEBOUNCE_COUNTER = 0
|
||||||
|
FETCH_TODAY_DEBOUNCE_SECONDS = 60
|
||||||
PYTHON_LOCATION = None
|
PYTHON_LOCATION = None
|
||||||
HEARTBEATS = queue.Queue()
|
HEARTBEATS = queue.Queue()
|
||||||
HEARTBEAT_FREQUENCY = 2 # minutes between logging heartbeat when editing same file
|
HEARTBEAT_FREQUENCY = 2 # minutes between logging heartbeat when editing same file
|
||||||
@ -180,21 +193,59 @@ def resources_folder():
|
|||||||
return os.path.join(os.path.expanduser('~'), '.wakatime')
|
return os.path.join(os.path.expanduser('~'), '.wakatime')
|
||||||
|
|
||||||
|
|
||||||
def update_status_bar(status):
|
def update_status_bar(status=None, debounced=False, msg=None):
|
||||||
"""Updates the status bar."""
|
"""Updates the status bar."""
|
||||||
|
global LAST_FETCH_TODAY_CODING_TIME, FETCH_TODAY_DEBOUNCE_COUNTER
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if SETTINGS.get('status_bar_message'):
|
if not msg and SETTINGS.get('status_bar_message') is not False and SETTINGS.get('status_bar_enabled'):
|
||||||
msg = datetime.now().strftime(SETTINGS.get('status_bar_message_fmt'))
|
if SETTINGS.get('status_bar_coding_activity') and status == 'OK':
|
||||||
if '{status}' in msg:
|
if debounced:
|
||||||
msg = msg.format(status=status)
|
FETCH_TODAY_DEBOUNCE_COUNTER -= 1
|
||||||
|
if debounced or not LAST_FETCH_TODAY_CODING_TIME:
|
||||||
|
now = int(time.time())
|
||||||
|
if LAST_FETCH_TODAY_CODING_TIME and (FETCH_TODAY_DEBOUNCE_COUNTER > 0 or LAST_FETCH_TODAY_CODING_TIME > now - FETCH_TODAY_DEBOUNCE_SECONDS):
|
||||||
|
return
|
||||||
|
LAST_FETCH_TODAY_CODING_TIME = now
|
||||||
|
FetchStatusBarCodingTime().start()
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
FETCH_TODAY_DEBOUNCE_COUNTER += 1
|
||||||
|
set_timeout(lambda: update_status_bar(status, debounced=True), FETCH_TODAY_DEBOUNCE_SECONDS)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
msg = '{prefix}: {status}'.format(prefix=STATUS_BAR_PREFIX, status=status)
|
||||||
|
|
||||||
|
if msg:
|
||||||
active_window = sublime.active_window()
|
active_window = sublime.active_window()
|
||||||
if active_window:
|
if active_window:
|
||||||
for view in active_window.views():
|
for view in active_window.views():
|
||||||
view.set_status('wakatime', msg)
|
view.set_status('wakatime', msg)
|
||||||
|
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
set_timeout(lambda: update_status_bar(status), 0)
|
set_timeout(lambda: update_status_bar(status=status, debounced=debounced, msg=msg), 0)
|
||||||
|
|
||||||
|
|
||||||
|
class FetchStatusBarCodingTime(threading.Thread):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
|
self.api_key = SETTINGS.get('api_key', '')
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if not self.api_key:
|
||||||
|
log(DEBUG, 'Missing WakaTime API key.')
|
||||||
|
return
|
||||||
|
|
||||||
|
url = 'https://wakatime.com/api/v1/users/current/summaries?start=today&end=today&api_key={}'.format(self.api_key)
|
||||||
|
try:
|
||||||
|
with closing(urllib2.urlopen(url)) as response:
|
||||||
|
grand_total_text = json.loads(u(response.read()))['data'][0]['grand_total']['text']
|
||||||
|
msg = '{} Today: {}'.format(STATUS_BAR_PREFIX, grand_total_text)
|
||||||
|
update_status_bar(msg=msg)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def prompt_api_key():
|
def prompt_api_key():
|
||||||
@ -648,7 +699,7 @@ def plugin_loaded():
|
|||||||
SETTINGS = sublime.load_settings(SETTINGS_FILE)
|
SETTINGS = sublime.load_settings(SETTINGS_FILE)
|
||||||
|
|
||||||
log(INFO, 'Initializing WakaTime plugin v%s' % __version__)
|
log(INFO, 'Initializing WakaTime plugin v%s' % __version__)
|
||||||
update_status_bar('Initializing')
|
update_status_bar('Initializing...')
|
||||||
|
|
||||||
if not python_binary():
|
if not python_binary():
|
||||||
log(WARNING, 'Python binary not found.')
|
log(WARNING, 'Python binary not found.')
|
||||||
@ -664,6 +715,7 @@ def plugin_loaded():
|
|||||||
def after_loaded():
|
def after_loaded():
|
||||||
if not prompt_api_key():
|
if not prompt_api_key():
|
||||||
set_timeout(after_loaded, 0.5)
|
set_timeout(after_loaded, 0.5)
|
||||||
|
update_status_bar('OK')
|
||||||
|
|
||||||
|
|
||||||
# need to call plugin_loaded because only ST3 will auto-call it
|
# need to call plugin_loaded because only ST3 will auto-call it
|
||||||
|
@ -21,12 +21,13 @@
|
|||||||
// POSIX regular expressions will bypass your ignore setting.
|
// POSIX regular expressions will bypass your ignore setting.
|
||||||
"include": [".*"],
|
"include": [".*"],
|
||||||
|
|
||||||
// Status bar message. Set to false to hide status bar message.
|
// Status bar for surfacing errors and displaying today's coding time. Set
|
||||||
// Defaults to true.
|
// to false to hide. Defaults to true.
|
||||||
"status_bar_message": true,
|
"status_bar_enabled": true,
|
||||||
|
|
||||||
// Status bar message format.
|
// Show today's coding activity in WakaTime status bar item.
|
||||||
"status_bar_message_fmt": "WakaTime {status} %I:%M %p",
|
// Defaults to true.
|
||||||
|
"status_bar_coding_activity": true,
|
||||||
|
|
||||||
// Obfuscate file paths when sending to API. Your dashboard will no longer display coding activity per file.
|
// Obfuscate file paths when sending to API. Your dashboard will no longer display coding activity per file.
|
||||||
"hidefilenames": false,
|
"hidefilenames": false,
|
||||||
|
Loading…
Reference in New Issue
Block a user