diff kitten: Fix exiting while highlighting is incomplete causes kitten to hang until highlighting is done
This commit is contained in:
parent
4778e0eb23
commit
2c0ac895e6
@ -4,7 +4,10 @@
|
|||||||
import concurrent
|
import concurrent
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import IO, Dict, Iterable, List, Optional, Tuple, Union, cast
|
from concurrent.futures import ProcessPoolExecutor
|
||||||
|
from typing import (
|
||||||
|
IO, Dict, Iterable, Iterator, List, Optional, Tuple, Union, cast
|
||||||
|
)
|
||||||
|
|
||||||
from pygments import highlight # type: ignore
|
from pygments import highlight # type: ignore
|
||||||
from pygments.formatter import Formatter # type: ignore
|
from pygments.formatter import Formatter # type: ignore
|
||||||
@ -136,10 +139,22 @@ def highlight_for_diff(path: str, aliases: Dict[str, str]) -> DiffHighlight:
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
process_pool_executor: Optional[ProcessPoolExecutor] = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_highlight_processes() -> Iterator[int]:
|
||||||
|
if process_pool_executor is None:
|
||||||
|
return
|
||||||
|
for pid in process_pool_executor._processes:
|
||||||
|
yield pid
|
||||||
|
|
||||||
|
|
||||||
def highlight_collection(collection: Collection, aliases: Optional[Dict[str, str]] = None) -> Union[str, Dict[str, DiffHighlight]]:
|
def highlight_collection(collection: Collection, aliases: Optional[Dict[str, str]] = None) -> Union[str, Dict[str, DiffHighlight]]:
|
||||||
|
global process_pool_executor
|
||||||
jobs = {}
|
jobs = {}
|
||||||
ans: Dict[str, DiffHighlight] = {}
|
ans: Dict[str, DiffHighlight] = {}
|
||||||
with get_process_pool_executor(prefer_fork=True) as executor:
|
with get_process_pool_executor(prefer_fork=True) as executor:
|
||||||
|
process_pool_executor = executor
|
||||||
for path, item_type, other_path in collection:
|
for path, item_type, other_path in collection:
|
||||||
if item_type != 'rename':
|
if item_type != 'rename':
|
||||||
for p in (path, other_path):
|
for p in (path, other_path):
|
||||||
@ -159,8 +174,9 @@ def highlight_collection(collection: Collection, aliases: Optional[Dict[str, str
|
|||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
# kitty +runpy "from kittens.diff.highlight import main; main()" file
|
# kitty +runpy "from kittens.diff.highlight import main; main()" file
|
||||||
from .options.types import defaults
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from .options.types import defaults
|
||||||
initialize_highlighter()
|
initialize_highlighter()
|
||||||
with open(sys.argv[-1]) as f:
|
with open(sys.argv[-1]) as f:
|
||||||
highlighted = highlight_data(f.read(), f.name, defaults.syntax_aliases)
|
highlighted = highlight_data(f.read(), f.name, defaults.syntax_aliases)
|
||||||
|
|||||||
@ -13,7 +13,7 @@ from contextlib import suppress
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
from typing import (
|
from typing import (
|
||||||
Any, DefaultDict, Dict, Iterable, List, Optional, Tuple, Union
|
Any, DefaultDict, Dict, Iterable, Iterator, List, Optional, Tuple, Union
|
||||||
)
|
)
|
||||||
|
|
||||||
from kitty.cli import CONFIG_HELP, parse_args
|
from kitty.cli import CONFIG_HELP, parse_args
|
||||||
@ -44,7 +44,8 @@ from .search import BadRegex, Search
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from .highlight import (
|
from .highlight import (
|
||||||
DiffHighlight, highlight_collection, initialize_highlighter
|
DiffHighlight, get_highlight_processes, highlight_collection,
|
||||||
|
initialize_highlighter
|
||||||
)
|
)
|
||||||
has_highlighter = True
|
has_highlighter = True
|
||||||
DiffHighlight
|
DiffHighlight
|
||||||
@ -54,6 +55,10 @@ except ImportError:
|
|||||||
def highlight_collection(collection: 'Collection', aliases: Optional[Dict[str, str]] = None) -> Union[str, Dict[str, 'DiffHighlight']]:
|
def highlight_collection(collection: 'Collection', aliases: Optional[Dict[str, str]] = None) -> Union[str, Dict[str, 'DiffHighlight']]:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
def get_highlight_processes() -> Iterator[int]:
|
||||||
|
if has_highlighter:
|
||||||
|
yield -1
|
||||||
|
|
||||||
|
|
||||||
INITIALIZING, COLLECTED, DIFFED, COMMAND, MESSAGE = range(5)
|
INITIALIZING, COLLECTED, DIFFED, COMMAND, MESSAGE = range(5)
|
||||||
|
|
||||||
@ -90,14 +95,18 @@ class DiffHandler(Handler):
|
|||||||
if self.current_context_count < 0:
|
if self.current_context_count < 0:
|
||||||
self.current_context_count = self.original_context_count = self.opts.num_context_lines
|
self.current_context_count = self.original_context_count = self.opts.num_context_lines
|
||||||
self.highlighting_done = False
|
self.highlighting_done = False
|
||||||
|
self.doing_background_work = ''
|
||||||
self.restore_position: Optional[Reference] = None
|
self.restore_position: Optional[Reference] = None
|
||||||
for key_def, action in self.opts.key_definitions.items():
|
for key_def, action in self.opts.key_definitions.items():
|
||||||
self.add_shortcut(action, key_def)
|
self.add_shortcut(action, key_def)
|
||||||
|
|
||||||
|
def terminate(self, return_code: int = 0) -> None:
|
||||||
|
self.quit_loop(return_code)
|
||||||
|
|
||||||
def perform_action(self, action: KeyAction) -> None:
|
def perform_action(self, action: KeyAction) -> None:
|
||||||
func, args = action
|
func, args = action
|
||||||
if func == 'quit':
|
if func == 'quit':
|
||||||
self.quit_loop(0)
|
self.terminate()
|
||||||
return
|
return
|
||||||
if self.state <= DIFFED:
|
if self.state <= DIFFED:
|
||||||
if func == 'scroll_by':
|
if func == 'scroll_by':
|
||||||
@ -130,6 +139,7 @@ class DiffHandler(Handler):
|
|||||||
def create_collection(self) -> None:
|
def create_collection(self) -> None:
|
||||||
|
|
||||||
def collect_done(collection: Collection) -> None:
|
def collect_done(collection: Collection) -> None:
|
||||||
|
self.doing_background_work = ''
|
||||||
self.collection = collection
|
self.collection = collection
|
||||||
self.state = COLLECTED
|
self.state = COLLECTED
|
||||||
self.generate_diff()
|
self.generate_diff()
|
||||||
@ -139,13 +149,15 @@ class DiffHandler(Handler):
|
|||||||
self.asyncio_loop.call_soon_threadsafe(collect_done, collection)
|
self.asyncio_loop.call_soon_threadsafe(collect_done, collection)
|
||||||
|
|
||||||
self.asyncio_loop.run_in_executor(None, collect, self.left, self.right)
|
self.asyncio_loop.run_in_executor(None, collect, self.left, self.right)
|
||||||
|
self.doing_background_work = 'collecting'
|
||||||
|
|
||||||
def generate_diff(self) -> None:
|
def generate_diff(self) -> None:
|
||||||
|
|
||||||
def diff_done(diff_map: Union[str, Dict[str, Patch]]) -> None:
|
def diff_done(diff_map: Union[str, Dict[str, Patch]]) -> None:
|
||||||
|
self.doing_background_work = ''
|
||||||
if isinstance(diff_map, str):
|
if isinstance(diff_map, str):
|
||||||
self.report_traceback_on_exit = diff_map
|
self.report_traceback_on_exit = diff_map
|
||||||
self.quit_loop(1)
|
self.terminate(1)
|
||||||
return
|
return
|
||||||
self.state = DIFFED
|
self.state = DIFFED
|
||||||
self.diff_map = diff_map
|
self.diff_map = diff_map
|
||||||
@ -163,7 +175,7 @@ class DiffHandler(Handler):
|
|||||||
initialize_highlighter(self.opts.pygments_style)
|
initialize_highlighter(self.opts.pygments_style)
|
||||||
except StyleNotFound as e:
|
except StyleNotFound as e:
|
||||||
self.report_traceback_on_exit = str(e)
|
self.report_traceback_on_exit = str(e)
|
||||||
self.quit_loop(1)
|
self.terminate(1)
|
||||||
return
|
return
|
||||||
self.syntax_highlight()
|
self.syntax_highlight()
|
||||||
|
|
||||||
@ -172,13 +184,15 @@ class DiffHandler(Handler):
|
|||||||
self.asyncio_loop.call_soon_threadsafe(diff_done, diff_map)
|
self.asyncio_loop.call_soon_threadsafe(diff_done, diff_map)
|
||||||
|
|
||||||
self.asyncio_loop.run_in_executor(None, diff, self.collection, self.current_context_count)
|
self.asyncio_loop.run_in_executor(None, diff, self.collection, self.current_context_count)
|
||||||
|
self.doing_background_work = 'diffing'
|
||||||
|
|
||||||
def syntax_highlight(self) -> None:
|
def syntax_highlight(self) -> None:
|
||||||
|
|
||||||
def highlighting_done(hdata: Union[str, Dict[str, 'DiffHighlight']]) -> None:
|
def highlighting_done(hdata: Union[str, Dict[str, 'DiffHighlight']]) -> None:
|
||||||
|
self.doing_background_work = ''
|
||||||
if isinstance(hdata, str):
|
if isinstance(hdata, str):
|
||||||
self.report_traceback_on_exit = hdata
|
self.report_traceback_on_exit = hdata
|
||||||
self.quit_loop(1)
|
self.terminate(1)
|
||||||
return
|
return
|
||||||
set_highlight_data(hdata)
|
set_highlight_data(hdata)
|
||||||
self.render_diff()
|
self.render_diff()
|
||||||
@ -189,6 +203,7 @@ class DiffHandler(Handler):
|
|||||||
self.asyncio_loop.call_soon_threadsafe(highlighting_done, result)
|
self.asyncio_loop.call_soon_threadsafe(highlighting_done, result)
|
||||||
|
|
||||||
self.asyncio_loop.run_in_executor(None, highlight, self.collection, self.opts.syntax_aliases)
|
self.asyncio_loop.run_in_executor(None, highlight, self.collection, self.opts.syntax_aliases)
|
||||||
|
self.doing_background_work = 'highlighting'
|
||||||
|
|
||||||
def calculate_statistics(self) -> None:
|
def calculate_statistics(self) -> None:
|
||||||
self.added_count = self.collection.added_count
|
self.added_count = self.collection.added_count
|
||||||
@ -532,10 +547,10 @@ class DiffHandler(Handler):
|
|||||||
self.draw_screen()
|
self.draw_screen()
|
||||||
|
|
||||||
def on_interrupt(self) -> None:
|
def on_interrupt(self) -> None:
|
||||||
self.quit_loop(1)
|
self.terminate(1)
|
||||||
|
|
||||||
def on_eot(self) -> None:
|
def on_eot(self) -> None:
|
||||||
self.quit_loop(1)
|
self.terminate(1)
|
||||||
|
|
||||||
|
|
||||||
OPTIONS = partial('''\
|
OPTIONS = partial('''\
|
||||||
@ -639,9 +654,10 @@ def main(args: List[str]) -> None:
|
|||||||
for message in showwarning.warnings:
|
for message in showwarning.warnings:
|
||||||
from kitty.utils import safe_print
|
from kitty.utils import safe_print
|
||||||
safe_print(message, file=sys.stderr)
|
safe_print(message, file=sys.stderr)
|
||||||
highlight_processes = getattr(highlight_collection, 'processes', ())
|
if handler.doing_background_work == 'highlighting':
|
||||||
terminate_processes(tuple(highlight_processes))
|
terminate_processes(tuple(get_highlight_processes()))
|
||||||
terminate_processes(tuple(worker_processes))
|
elif handler.doing_background_work == 'diffing':
|
||||||
|
terminate_processes(tuple(worker_processes))
|
||||||
if loop.return_code != 0:
|
if loop.return_code != 0:
|
||||||
if handler.report_traceback_on_exit:
|
if handler.report_traceback_on_exit:
|
||||||
print(handler.report_traceback_on_exit, file=sys.stderr)
|
print(handler.report_traceback_on_exit, file=sys.stderr)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user