mirror of
https://github.com/wakatime/sublime-wakatime.git
synced 2023-08-10 21:13:02 +03:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
67d8b0d24f | |||
b8b2f4944b | |||
a20161164c | |||
405211bb07 | |||
ffc879c4eb | |||
1e23919694 | |||
b2086a3cd2 | |||
005b07520c | |||
60608bd322 | |||
cde8f8f1de | |||
4adfca154c | |||
f7b3924a30 | |||
db00024455 |
31
HISTORY.rst
31
HISTORY.rst
@ -3,11 +3,40 @@ History
|
|||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
||||||
|
8.7.0 (2019-05-29)
|
||||||
|
++++++++++++++++++
|
||||||
|
|
||||||
|
- Prevent creating user sublime-settings file when api key already exists in
|
||||||
|
common wakatime.cfg file.
|
||||||
|
`sublime-wakatime#98 <https://github.com/wakatime/sublime-wakatime/issues/98>`_
|
||||||
|
|
||||||
|
|
||||||
|
8.6.1 (2019-05-28)
|
||||||
|
++++++++++++++++++
|
||||||
|
|
||||||
|
- Fix parsing common wakatime.cfg file.
|
||||||
|
`sublime-wakatime#98 <https://github.com/wakatime/sublime-wakatime/issues/98>`_
|
||||||
|
|
||||||
|
|
||||||
|
8.6.0 (2019-05-27)
|
||||||
|
++++++++++++++++++
|
||||||
|
|
||||||
|
- Prevent prompting for api key when found from config file.
|
||||||
|
`sublime-wakatime#98 <https://github.com/wakatime/sublime-wakatime/issues/98>`_
|
||||||
|
|
||||||
|
|
||||||
|
8.5.0 (2019-05-10)
|
||||||
|
++++++++++++++++++
|
||||||
|
|
||||||
|
- Remove clock icon from status bar.
|
||||||
|
- Use wakatime-cli to fetch status bar coding time.
|
||||||
|
|
||||||
|
|
||||||
8.4.2 (2019-05-07)
|
8.4.2 (2019-05-07)
|
||||||
++++++++++++++++++
|
++++++++++++++++++
|
||||||
|
|
||||||
- Upgrade wakatime-cli to v11.0.0.
|
- Upgrade wakatime-cli to v11.0.0.
|
||||||
- Rename largument --show-time-today to --today.
|
- Rename argument --show-time-today to --today.
|
||||||
- New argument --show-time-today for printing Today's coding time.
|
- New argument --show-time-today for printing Today's coding time.
|
||||||
|
|
||||||
|
|
||||||
|
115
WakaTime.py
115
WakaTime.py
@ -8,7 +8,7 @@ Website: https://wakatime.com/
|
|||||||
==========================================================="""
|
==========================================================="""
|
||||||
|
|
||||||
|
|
||||||
__version__ = '8.4.2'
|
__version__ = '8.7.0'
|
||||||
|
|
||||||
|
|
||||||
import sublime
|
import sublime
|
||||||
@ -26,7 +26,6 @@ import threading
|
|||||||
import traceback
|
import traceback
|
||||||
import urllib
|
import urllib
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from contextlib import closing
|
|
||||||
from subprocess import STDOUT, PIPE
|
from subprocess import STDOUT, PIPE
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
try:
|
try:
|
||||||
@ -41,11 +40,6 @@ 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)
|
||||||
@ -53,8 +47,6 @@ 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
|
||||||
@ -78,8 +70,6 @@ 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
|
||||||
@ -138,7 +128,6 @@ 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
|
||||||
SEND_BUFFER_SECONDS = 30 # seconds between sending buffered heartbeats to API
|
SEND_BUFFER_SECONDS = 30 # seconds between sending buffered heartbeats to API
|
||||||
API_SUMMARIES_URL = 'https://api.wakatime.com/api/v1/users/current/summaries?start=today&end=today&api_key={}'
|
|
||||||
|
|
||||||
|
|
||||||
# Log Levels
|
# Log Levels
|
||||||
@ -151,9 +140,45 @@ ERROR = 'ERROR'
|
|||||||
# add wakatime package to path
|
# add wakatime package to path
|
||||||
sys.path.insert(0, os.path.join(PLUGIN_DIR, 'packages'))
|
sys.path.insert(0, os.path.join(PLUGIN_DIR, 'packages'))
|
||||||
try:
|
try:
|
||||||
from wakatime.main import parseConfigFile
|
from wakatime.configs import parseConfigFile
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
def parseConfigFile():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class ApiKey(object):
|
||||||
|
_key = None
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
if self._key:
|
||||||
|
return self._key
|
||||||
|
|
||||||
|
key = SETTINGS.get('api_key')
|
||||||
|
if key:
|
||||||
|
self._key = key
|
||||||
|
return self._key
|
||||||
|
|
||||||
|
try:
|
||||||
|
configs = parseConfigFile()
|
||||||
|
if configs:
|
||||||
|
if configs.has_option('settings', 'api_key'):
|
||||||
|
key = configs.get('settings', 'api_key')
|
||||||
|
if key:
|
||||||
|
self._key = key
|
||||||
|
return self._key
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return self._key
|
||||||
|
|
||||||
|
def write(self, key):
|
||||||
|
global SETTINGS
|
||||||
|
self._key = key
|
||||||
|
SETTINGS.set('api_key', str(key))
|
||||||
|
sublime.save_settings(SETTINGS_FILE)
|
||||||
|
|
||||||
|
|
||||||
|
APIKEY = ApiKey()
|
||||||
|
|
||||||
|
|
||||||
def set_timeout(callback, seconds):
|
def set_timeout(callback, seconds):
|
||||||
@ -215,7 +240,7 @@ def update_status_bar(status=None, debounced=False, msg=None):
|
|||||||
set_timeout(lambda: update_status_bar(status, debounced=True), FETCH_TODAY_DEBOUNCE_SECONDS)
|
set_timeout(lambda: update_status_bar(status, debounced=True), FETCH_TODAY_DEBOUNCE_SECONDS)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
msg = '{prefix}: {status}'.format(prefix=STATUS_BAR_PREFIX, status=status)
|
msg = 'WakaTime: {status}'.format(status=status)
|
||||||
|
|
||||||
if msg:
|
if msg:
|
||||||
active_window = sublime.active_window()
|
active_window = sublime.active_window()
|
||||||
@ -232,45 +257,63 @@ class FetchStatusBarCodingTime(threading.Thread):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
self.api_key = SETTINGS.get('api_key', '')
|
self.debug = SETTINGS.get('debug')
|
||||||
|
self.api_key = APIKEY.read() or ''
|
||||||
|
self.proxy = SETTINGS.get('proxy')
|
||||||
|
self.python_binary = SETTINGS.get('python_binary')
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.api_key:
|
if not self.api_key:
|
||||||
log(DEBUG, 'Missing WakaTime API key.')
|
log(DEBUG, 'Missing WakaTime API key.')
|
||||||
return
|
return
|
||||||
|
|
||||||
url = API_SUMMARIES_URL.format(self.api_key)
|
python = self.python_binary
|
||||||
|
if not python or not python.strip():
|
||||||
|
python = python_binary()
|
||||||
|
if not python:
|
||||||
|
log(DEBUG, 'Missing Python.')
|
||||||
|
return
|
||||||
|
|
||||||
|
ua = 'sublime/%d sublime-wakatime/%s' % (ST_VERSION, __version__)
|
||||||
|
cmd = [
|
||||||
|
python,
|
||||||
|
API_CLIENT,
|
||||||
|
'--today',
|
||||||
|
'--key', str(bytes.decode(self.api_key.encode('utf8'))),
|
||||||
|
'--plugin', ua,
|
||||||
|
]
|
||||||
|
if self.debug:
|
||||||
|
cmd.append('--verbose')
|
||||||
|
if self.proxy:
|
||||||
|
cmd.extend(['--proxy', self.proxy])
|
||||||
|
|
||||||
|
log(DEBUG, ' '.join(obfuscate_apikey(cmd)))
|
||||||
try:
|
try:
|
||||||
with closing(urllib2.urlopen(url)) as response:
|
process = Popen(cmd, stdout=PIPE, stderr=STDOUT)
|
||||||
grand_total_text = json.loads(u(response.read()))['data'][0]['grand_total']['text']
|
output, err = process.communicate()
|
||||||
msg = '{} Today: {}'.format(STATUS_BAR_PREFIX, grand_total_text)
|
output = u(output)
|
||||||
|
retcode = process.poll()
|
||||||
|
if not retcode and output:
|
||||||
|
msg = 'Today: {output}'.format(output=output)
|
||||||
update_status_bar(msg=msg)
|
update_status_bar(msg=msg)
|
||||||
|
else:
|
||||||
|
log(DEBUG, 'wakatime-core today exited with status: {0}'.format(retcode))
|
||||||
|
if output:
|
||||||
|
log(DEBUG, u('wakatime-core today output: {0}').format(output))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def prompt_api_key():
|
def prompt_api_key():
|
||||||
global SETTINGS
|
if APIKEY.read():
|
||||||
|
|
||||||
if SETTINGS.get('api_key'):
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
default_key = ''
|
|
||||||
try:
|
|
||||||
configs = parseConfigFile()
|
|
||||||
if configs is not None:
|
|
||||||
if configs.has_option('settings', 'api_key'):
|
|
||||||
default_key = configs.get('settings', 'api_key')
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
window = sublime.active_window()
|
window = sublime.active_window()
|
||||||
if window:
|
if window:
|
||||||
def got_key(text):
|
def got_key(text):
|
||||||
if text:
|
if text:
|
||||||
SETTINGS.set('api_key', str(text))
|
APIKEY.write(text)
|
||||||
sublime.save_settings(SETTINGS_FILE)
|
window.show_input_panel('[WakaTime] Enter your wakatime.com api key:', '', got_key, None, None)
|
||||||
window.show_input_panel('[WakaTime] Enter your wakatime.com api key:', default_key, got_key, None, None)
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
log(ERROR, 'Could not prompt for api key because no window found.')
|
log(ERROR, 'Could not prompt for api key because no window found.')
|
||||||
@ -545,7 +588,7 @@ class SendHeartbeatsThread(threading.Thread):
|
|||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
self.debug = SETTINGS.get('debug')
|
self.debug = SETTINGS.get('debug')
|
||||||
self.api_key = SETTINGS.get('api_key', '')
|
self.api_key = APIKEY.read() or ''
|
||||||
self.ignore = SETTINGS.get('ignore', [])
|
self.ignore = SETTINGS.get('ignore', [])
|
||||||
self.include = SETTINGS.get('include', [])
|
self.include = SETTINGS.get('include', [])
|
||||||
self.hidefilenames = SETTINGS.get('hidefilenames')
|
self.hidefilenames = SETTINGS.get('hidefilenames')
|
||||||
|
Reference in New Issue
Block a user