mirror of
https://github.com/sstent/sublime-text-3.git
synced 2026-01-26 15:11:55 +00:00
135 lines
3.9 KiB
Python
135 lines
3.9 KiB
Python
#
|
|
# queue.py
|
|
# Part of SublimeLinter3, a code checking framework for Sublime Text 3
|
|
#
|
|
# Written by Ryan Hileman and Aparajita Fishman
|
|
#
|
|
# Project: https://github.com/SublimeLinter/SublimeLinter3
|
|
# License: MIT
|
|
#
|
|
|
|
"""This module provides a threaded queue for lint requests."""
|
|
|
|
from queue import Queue, Empty
|
|
import threading
|
|
import traceback
|
|
import time
|
|
|
|
from . import persist, util
|
|
|
|
|
|
class Daemon:
|
|
|
|
"""
|
|
This class provides a threaded queue that dispatches lints.
|
|
|
|
The following operations can be added to the queue:
|
|
|
|
hit - Queue a lint for a given view
|
|
delay - Queue a delay for a number of milliseconds
|
|
reload - Indicates the main plugin was reloaded
|
|
|
|
"""
|
|
|
|
MIN_DELAY = 0.1
|
|
running = False
|
|
callback = None
|
|
q = Queue()
|
|
last_runs = {}
|
|
|
|
def start(self, callback):
|
|
"""Start the daemon thread that runs loop."""
|
|
self.callback = callback
|
|
|
|
if self.running:
|
|
self.q.put('reload')
|
|
else:
|
|
self.running = True
|
|
threading.Thread(target=self.loop).start()
|
|
|
|
def loop(self):
|
|
"""Continually check the queue for new items and process them."""
|
|
|
|
last_runs = {}
|
|
|
|
while True:
|
|
try:
|
|
try:
|
|
item = self.q.get(block=True, timeout=self.MIN_DELAY)
|
|
except Empty:
|
|
for view_id, (timestamp, delay) in last_runs.copy().items():
|
|
# Lint the view if we have gone past the time
|
|
# at which the lint wants to run.
|
|
if time.monotonic() > timestamp + delay:
|
|
self.last_runs[view_id] = time.monotonic()
|
|
del last_runs[view_id]
|
|
self.lint(view_id, timestamp)
|
|
|
|
continue
|
|
|
|
if isinstance(item, tuple):
|
|
view_id, timestamp, delay = item
|
|
|
|
if view_id in self.last_runs and timestamp < self.last_runs[view_id]:
|
|
continue
|
|
|
|
last_runs[view_id] = timestamp, delay
|
|
|
|
elif isinstance(item, (int, float)):
|
|
time.sleep(item)
|
|
|
|
elif isinstance(item, str):
|
|
if item == 'reload':
|
|
persist.printf('daemon detected a reload')
|
|
self.last_runs.clear()
|
|
last_runs.clear()
|
|
else:
|
|
persist.printf('unknown message sent to daemon:', item)
|
|
except:
|
|
persist.printf('error in SublimeLinter daemon:')
|
|
persist.printf('-' * 20)
|
|
persist.printf(traceback.format_exc())
|
|
persist.printf('-' * 20)
|
|
|
|
def hit(self, view):
|
|
"""Add a lint request to the queue, return the time at which the request was enqueued."""
|
|
timestamp = time.monotonic()
|
|
self.q.put((view.id(), timestamp, self.get_delay(view)))
|
|
return timestamp
|
|
|
|
def delay(self, milliseconds=100):
|
|
"""Add a millisecond delay to the queue."""
|
|
self.q.put(milliseconds / 1000.0)
|
|
|
|
def lint(self, view_id, timestamp):
|
|
"""
|
|
Call back into the main plugin to lint the given view.
|
|
|
|
timestamp is used to determine if the view has been modified
|
|
since the lint was requested.
|
|
|
|
"""
|
|
self.callback(view_id, timestamp)
|
|
|
|
def get_delay(self, view):
|
|
"""
|
|
Return the delay between a lint request and when it will be processed.
|
|
|
|
If the lint mode is not background, there is no delay. Otherwise, if
|
|
a "delay" setting is not available in any of the settings, MIN_DELAY is used.
|
|
|
|
"""
|
|
|
|
if persist.settings.get('lint_mode') != 'background':
|
|
return 0
|
|
|
|
delay = (util.get_view_rc_settings(view) or {}).get('delay')
|
|
|
|
if delay is None:
|
|
delay = persist.settings.get('delay', self.MIN_DELAY)
|
|
|
|
return delay
|
|
|
|
|
|
queue = Daemon()
|