Skip to content

Commit

Permalink
Merge pull request #15 from andfoy/cell_folding
Browse files Browse the repository at this point in the history
PR: Add support for textDocument/foldingRange call for code cells
  • Loading branch information
andfoy committed Dec 11, 2020
2 parents 3f24912 + 8188942 commit feb3669
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pytest -x -v pyls_spyder/tests
| LSP method | Spyder extensions |
|:-----------------------------:|:------------------------------------------------:|
| `textDocument/documentSymbol` | Find code cells `# %%` and block comments `# --` |
| `textDocument/foldingRange` | Return code cells `# %%` as code folding regions |

## Plugin configuration options
This plugin can be configured by using the key `pyls_spyder` when calling `workspace/didChangeConfiguration` on the pyls. Each configuration option is described below:
Expand Down
38 changes: 38 additions & 0 deletions pyls_spyder/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ def create_symbol(name: str, document: Document,
}


def create_fold_region(start_line: int, end_line: int):
return {
'startLine': start_line,
'endLine': end_line,
}


@hookimpl
def pyls_document_symbols(config: Config,
workspace: Workspace,
Expand Down Expand Up @@ -140,3 +147,34 @@ def pyls_document_symbols(config: Config,
spyder_symbols = sorted(
spyder_symbols, key=lambda x: x['location']['range']['start']['line'])
return spyder_symbols


@hookimpl
def pyls_folding_range(
config: Config,
workspace: Workspace,
document: Document) -> List[Dict]:
lines = document.lines
cell_stack = []
cells = []
for line_num, line in enumerate(lines):
cell_rule, cell_match = CELL_REGEX.match(line)
if cell_match is not None:
percentages = cell_match.group(1)
current_line, current_level, _ = peek_symbol(cell_stack)
if cell_rule != CELL_PERCENTAGE:
cell_level = current_level + 1
else:
cell_level = len(percentages) - 1
if cell_level > current_level:
cell_stack.insert(0, (line_num, cell_level, ''))
else:
while current_level >= cell_level:
cell_stack.pop(0)
cells.append(create_fold_region(current_line, line_num))
current_line, current_level, _ = peek_symbol(cell_stack)
cell_stack.insert(0, (line_num, cell_level, ''))
for line, _, name in cell_stack:
cells.append(create_fold_region(line, line_num + 1))
cells = sorted(cells, key=lambda x: x['startLine'])
return cells
22 changes: 21 additions & 1 deletion pyls_spyder/tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from unittest.mock import MagicMock

# Local imports
from pyls_spyder.plugin import pyls_document_symbols
from pyls_spyder.plugin import pyls_document_symbols, pyls_folding_range


DOC_URI = uris.from_fs_path(__file__)
Expand Down Expand Up @@ -143,3 +143,23 @@ def test_disable_block_comments(config, workspace):
kind = symbol['kind']
test_results.append((name, start, end, kind))
assert expected == test_results


def test_cell_folding_regions(config, workspace):
document = Document(DOC_URI, workspace, DOC)
regions = pyls_folding_range(config, workspace, document)
expected = [
(1, 23),
(6, 10),
(10, 15),
(12, 15),
(15, 23),
(20, 23),
(23, 25)
]
test_results = []
for region in regions:
start = region['startLine']
end = region['endLine']
test_results.append((start, end))
assert expected == test_results
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def get_description():
return data


REQUIREMENTS = ['python-language-server']
REQUIREMENTS = ['python-language-server >= 0.36.2']

setup(
name='pyls-spyder',
Expand Down

0 comments on commit feb3669

Please sign in to comment.