Ignore comments when select next/prev. Fixes #27763

This commit is contained in:
Ramya Achutha Rao 2017-06-06 15:50:38 -07:00
parent a53cce90d3
commit bd544519ab
4 changed files with 70 additions and 57 deletions

View file

@ -34,7 +34,10 @@ export function fetchSelectItem(direction: string): void {
let rootNode: Node = parseContent(editor.document.getText());
let newSelections: vscode.Selection[] = [];
editor.selections.forEach(selection => {
let updatedSelection = direction === 'next' ? nextItem(selection, editor, rootNode) : prevItem(selection, editor, rootNode);
const selectionStart = editor.document.offsetAt(selection.isReversed ? selection.active : selection.anchor);
const selectionEnd = editor.document.offsetAt(selection.isReversed ? selection.anchor : selection.active);
let updatedSelection = direction === 'next' ? nextItem(selectionStart, selectionEnd, editor, rootNode) : prevItem(selectionStart, selectionEnd, editor, rootNode);
newSelections.push(updatedSelection ? updatedSelection : selection);
});
editor.selections = newSelections;

View file

@ -7,90 +7,104 @@ import * as vscode from 'vscode';
import { getNode, getDeepestNode, findNextWord, findPrevWord } from './util';
import Node from '@emmetio/node';
export function nextItemHTML(selection: vscode.Selection, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
let offset = editor.document.offsetAt(selection.active);
let currentNode = getNode(rootNode, offset);
export function nextItemHTML(selectionStart: number, selectionEnd: number, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
let currentNode = getNode(rootNode, selectionEnd);
let nextNode: Node;
// Cursor is in the open tag, look for attributes
if (offset < currentNode.open.end) {
let attrSelection = getNextAttribute(selection, editor.document, currentNode);
if (attrSelection) {
return attrSelection;
if (currentNode.type !== 'comment') {
// If cursor is in the tag name, select tag
if (selectionEnd < currentNode.open.start + currentNode.name.length) {
return getSelectionFromNode(currentNode, editor.document);
}
// If cursor is in the open tag, look for attributes
if (selectionEnd < currentNode.open.end) {
let attrSelection = getNextAttribute(selectionStart, selectionEnd, editor.document, currentNode);
if (attrSelection) {
return attrSelection;
}
}
// Get the first child of current node which is right after the cursor and is not a comment
nextNode = currentNode.firstChild;
while (nextNode && (nextNode.start < selectionEnd || nextNode.type === 'comment')) {
nextNode = nextNode.nextSibling;
}
}
// Get the first child of current node which is right after the cursor
let nextNode = currentNode.firstChild;
while (nextNode && nextNode.start < offset) {
nextNode = nextNode.nextSibling;
}
// Get next sibling of current node or the parent
// Get next sibling of current node which is not a comment. If none is found try the same on the parent
while (!nextNode && currentNode) {
nextNode = currentNode.nextSibling;
currentNode = currentNode.parent;
if (currentNode.nextSibling) {
if (currentNode.nextSibling.type !== 'comment') {
nextNode = currentNode.nextSibling;
} else {
currentNode = currentNode.nextSibling;
}
} else {
currentNode = currentNode.parent;
}
}
return getSelectionFromNode(nextNode, editor.document);
}
export function prevItemHTML(selection: vscode.Selection, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
let offset = editor.document.offsetAt(selection.active);
let currentNode = getNode(rootNode, offset);
export function prevItemHTML(selectionStart: number, selectionEnd: number, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
let currentNode = getNode(rootNode, selectionStart);
let prevNode: Node;
// Cursor is in the open tag after the tag name
if (offset > currentNode.open.start + currentNode.name.length + 1 && offset <= currentNode.open.end) {
prevNode = currentNode;
}
if (currentNode.type !== 'comment' && selectionStart > currentNode.open.start + 1) {
// Cursor is inside the tag
if (!prevNode && offset > currentNode.open.end) {
if (!currentNode.firstChild) {
// No children, so current node should be selected
if (selectionStart < currentNode.open.end || !currentNode.firstChild) {
prevNode = currentNode;
} else {
// Select the child that appears just before the cursor
// Select the child that appears just before the cursor and is not a comment
prevNode = currentNode.firstChild;
while (prevNode.nextSibling && prevNode.nextSibling.end < offset) {
let oldOption: Node;
while (prevNode.nextSibling && prevNode.nextSibling.end < selectionStart) {
if (prevNode && prevNode.type !== 'comment') {
oldOption = prevNode;
}
prevNode = prevNode.nextSibling;
}
if (prevNode) {
prevNode = getDeepestNode(prevNode);
}
prevNode = getDeepestNode((prevNode && prevNode.type !== 'comment') ? prevNode : oldOption);
}
}
if (!prevNode && currentNode.previousSibling) {
prevNode = getDeepestNode(currentNode.previousSibling);
// Select previous sibling which is not a comment. If none found, then select parent
while (!prevNode && currentNode) {
if (currentNode.previousSibling) {
if (currentNode.previousSibling.type !== 'comment') {
prevNode = getDeepestNode(currentNode.previousSibling);
} else {
currentNode = currentNode.previousSibling;
}
} else {
prevNode = currentNode.parent;
}
}
if (!prevNode && currentNode.parent) {
prevNode = currentNode.parent;
}
let attrSelection = getPrevAttribute(selection, editor.document, prevNode);
let attrSelection = getPrevAttribute(selectionStart, selectionEnd, editor.document, prevNode);
return attrSelection ? attrSelection : getSelectionFromNode(prevNode, editor.document);
}
function getSelectionFromNode(node: Node, document: vscode.TextDocument): vscode.Selection {
if (node && node.open) {
let selectionStart = document.positionAt(node.open.start + 1);
let selectionEnd = node.type === 'comment' ? document.positionAt(node.open.end - 1) : selectionStart.translate(0, node.name.length);
let selectionEnd = selectionStart.translate(0, node.name.length);
return new vscode.Selection(selectionStart, selectionEnd);
}
}
function getNextAttribute(selection: vscode.Selection, document: vscode.TextDocument, node: Node): vscode.Selection {
function getNextAttribute(selectionStart: number, selectionEnd: number, document: vscode.TextDocument, node: Node): vscode.Selection {
if (!node.attributes || node.attributes.length === 0 || node.type === 'comment') {
return;
}
let selectionStart = document.offsetAt(selection.anchor);
let selectionEnd = document.offsetAt(selection.active);
for (let i = 0; i < node.attributes.length; i++) {
let attr = node.attributes[i];
@ -136,15 +150,12 @@ function getNextAttribute(selection: vscode.Selection, document: vscode.TextDocu
}
}
function getPrevAttribute(selection: vscode.Selection, document: vscode.TextDocument, node: Node): vscode.Selection {
function getPrevAttribute(selectionStart: number, selectionEnd: number, document: vscode.TextDocument, node: Node): vscode.Selection {
if (!node.attributes || node.attributes.length === 0 || node.type === 'comment') {
return;
}
let selectionStart = document.offsetAt(selection.anchor);
let selectionEnd = document.offsetAt(selection.active);
for (let i = node.attributes.length - 1; i >= 0; i--) {
let attr = node.attributes[i];

View file

@ -7,9 +7,7 @@ import * as vscode from 'vscode';
import { getNode, getDeepestNode, findNextWord, findPrevWord } from './util';
import Node from '@emmetio/node';
export function nextItemStylesheet(selection: vscode.Selection, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
let startOffset = editor.document.offsetAt(selection.anchor);
let endOffset = editor.document.offsetAt(selection.active);
export function nextItemStylesheet(startOffset: number, endOffset: number, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
let currentNode = getNode(rootNode, endOffset, true);
// Full property is selected, so select full property value next
@ -47,9 +45,7 @@ export function nextItemStylesheet(selection: vscode.Selection, editor: vscode.T
}
export function prevItemStylesheet(selection: vscode.Selection, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
let startOffset = editor.document.offsetAt(selection.anchor);
let endOffset = editor.document.offsetAt(selection.active);
export function prevItemStylesheet(startOffset: number, endOffset: number, editor: vscode.TextEditor, rootNode: Node): vscode.Selection {
let currentNode = getNode(rootNode, startOffset);
if (!currentNode) {
currentNode = rootNode;

View file

@ -134,8 +134,11 @@ export function getDeepestNode(node: Node): Node {
if (!node || !node.children || node.children.length === 0) {
return node;
}
return getDeepestNode(node.children[node.children.length - 1]);
for (let i = node.children.length - 1; i >= 0; i--) {
if (node.children[i].type !== 'comment') {
return getDeepestNode(node.children[i]);
}
}
}
export function findNextWord(propertyValue: string, pos: number): [number, number] {