-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Resolves #90
- Loading branch information
Heiko Nickerl
committed
Jun 25, 2018
1 parent
efff1f2
commit aba1953
Showing
6 changed files
with
121 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,25 @@ | ||
import logging | ||
|
||
import pygments | ||
from pygments import lexers, token | ||
from pygments.lexers.shell import BashLexer | ||
from urwid import Text | ||
|
||
from ui import theme, graphics | ||
from ui import graphics | ||
from ui.entrylist import List | ||
from ui.viewmodel import ViewModel | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class FilePreview(List): | ||
def __init__(self, model): | ||
super().__init__() | ||
self.model = model | ||
self.content = None | ||
self.model: ViewModel = model | ||
self.model.register(self) | ||
|
||
def on_update(self): | ||
with graphics.DRAW_LOCK: | ||
self.body.clear() | ||
content = self.model.file_content | ||
if content: | ||
lexer = find_lexer(self.model.current_entry.path, content) | ||
logger.info("Viewing file content - using {} for highlighting".format(type(lexer).__name__)) | ||
tokens = list(lexer.get_tokens(self.model.file_content)) | ||
# tabs are not rendered correctly, replace them with spaces | ||
tokens = replace_tabs(tokens) | ||
self.body.extend([Text(line) for line in bold_headings(inject_linenumbers(tokens))]) | ||
if self.model.filtered_file_content and self.model.filtered_file_content != self.content: | ||
self.content = self.model.filtered_file_content | ||
with graphics.DRAW_LOCK: | ||
self.body.clear() | ||
self.body.extend([Text(line.numbered_content) for line in self.content]) | ||
self.focus_position = 0 | ||
|
||
|
||
def replace_tabs(tokens): | ||
return [(attr, line.replace("\t", " ")) for attr, line in tokens] | ||
|
||
|
||
def find_lexer(filename: str, content: str): | ||
try: | ||
lexer = lexers.guess_lexer_for_filename(filename, content, stripnl=False, | ||
ensurenl=False) | ||
logger.debug('Detected lexer by filename') | ||
except pygments.util.ClassNotFound: | ||
try: | ||
lexer = lexers.guess_lexer(content, stripnl=False, ensurenl=False) | ||
logger.debug('Detected lexer by file content') | ||
except pygments.util.ClassNotFound: | ||
lexer = BashLexer(stripnl=False, ensurenl=False) | ||
logger.debug('Using fallback lexer') | ||
return lexer | ||
|
||
|
||
def inject_linenumbers(tokens): | ||
line = [] | ||
pos = 0 | ||
line.append((theme.line_number, u"{:>2} ".format(pos + 1))) | ||
for attr, token in tokens: | ||
while '\n' in token: | ||
index = token.index('\n') | ||
begin = token[:index] | ||
token = token[index + 1:] | ||
if begin: | ||
line.append((attr, begin)) | ||
pos += 1 | ||
yield line | ||
line = [(theme.line_number, u'{:>2} '.format(pos + 1))] | ||
if token: | ||
line.append((attr, token)) | ||
if len(line) > 1: | ||
yield line | ||
|
||
|
||
def bold_headings(lines): | ||
for line in lines: | ||
heading = False | ||
new_line = [] | ||
for attr, word in line: | ||
if attr is token.Generic.Heading or attr is token.Generic.Subheading: | ||
heading = True | ||
if heading and attr in token.Text: | ||
attr = 'bold' | ||
new_line.append((attr, word)) | ||
yield new_line |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import logging | ||
from typing import List, Pattern | ||
|
||
import pygments | ||
from pygments import lexers, token | ||
from pygments.lexers.shell import BashLexer | ||
|
||
from core.entry import Entry | ||
from ui import theme | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class HighlightedLine: | ||
def __init__(self, content, linenumber): | ||
self.content = self.bold_headings(content) | ||
self.linenumber = linenumber | ||
formatted_linenumber = [(theme.line_number, u'{:>2} '.format(linenumber))] | ||
self.numbered_content = [formatted_linenumber] + content | ||
|
||
def bold_headings(self, content): | ||
heading = False | ||
new_content = [] | ||
for attr, word in content: | ||
if attr is token.Generic.Heading or attr is token.Generic.Subheading: | ||
heading = True | ||
if heading and attr in token.Text: | ||
attr = 'bold' | ||
new_content.append((attr, word)) | ||
return new_content | ||
|
||
def matches(self, pattern: Pattern): | ||
if not pattern.pattern: | ||
return True | ||
for attr, word in self.content: | ||
if pattern.search(word): | ||
return True | ||
|
||
def __str__(self): | ||
return f"[{self.linenumber}: {self.content}]" | ||
|
||
|
||
def compute_highlighting(entry: Entry) -> List[HighlightedLine]: | ||
lexer = find_lexer(entry.path, entry.content) | ||
logger.info("Viewing file content - using {} for highlighting".format(type(lexer).__name__)) | ||
content = entry.content.replace('\t', " ") | ||
tokens = list(lexer.get_tokens(content)) | ||
return line_per_line(tokens) | ||
|
||
|
||
def find_lexer(filename: str, content: str): | ||
try: | ||
lexer = lexers.guess_lexer_for_filename(filename, content, stripnl=False, | ||
ensurenl=False) | ||
logger.debug('Detected lexer by filename') | ||
except pygments.util.ClassNotFound: | ||
try: | ||
lexer = lexers.guess_lexer(content, stripnl=False, ensurenl=False) | ||
logger.debug('Detected lexer by file content') | ||
except pygments.util.ClassNotFound: | ||
lexer = BashLexer(stripnl=False, ensurenl=False) | ||
logger.debug('Using fallback lexer') | ||
return lexer | ||
|
||
|
||
def line_per_line(tokens) -> List[HighlightedLine]: | ||
line = [] | ||
pos = 0 | ||
for attr, token in tokens: | ||
while '\n' in token: | ||
|
||
index = token.index('\n') | ||
begin = token[:index] | ||
token = token[index + 1:] | ||
if begin: | ||
line.append((attr, begin)) | ||
pos += 1 | ||
yield HighlightedLine(line, pos) | ||
line = [] | ||
if token: | ||
line.append((attr, token)) | ||
if len(line) > 1: | ||
yield HighlightedLine(line, pos) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters