Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial of 48 automate section numbering #49

Merged
merged 13 commits into from
Jan 28, 2024
Merged
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,29 @@ Key features tagged with `IPython`:
so that the created terminals are removed at end of a session and this feature
working properly for the next session.
- **Run `python` code interactively on IPython terminal**
- E.g., run a file, selection(s) of code, code section, run to line, run from line, ...
- Run a file, selection(s) of code, code section, run to line, run from line, ...
- Command line argument equivalent to `sys.argv` of `python foo.py argv`
- `%run` arguments (e.g., `-t` print timing info when running a `script.py`)
- **Settings for code custom sectioning and execution**
- Support multiple code section tags (e.g., `# %%`, `// ==`, or regular expression)
- Code section tag assocation option to a list of file extensions (e.g., `.py, .ts, .md`)
- `%run` arguments (e.g., `-t` print timing info when running a `script.py`)
- Command line argument equivalent to `sys.argv` of `python foo.py argv`
- Code section tag association option to a list of file extensions (e.g., `.py, .ts, .md`)
- **Editor visualization of code section blocks (issue #25)**
- Horizontal line divider and bolder text indicating each section starting line
- **Code section navigation and execution (issue #30)**
- A view in the primary sidebar providing section heading layout of associated files
- Use `cltr+shift+i b` to open `Code Section Navigator`
- Click on a heading focus the active editor to the section
- Various execution buttons are provided for file and section code execution
- ** Code section folding (issue #32)
- Section automatic numbering and execution options (#48)
- **Code section folding (issue #32)**
- Folding sections as region. See [VSCode Folding Documentation](https://code.visualstudio.com/docs/editor/codebasics#_folding).
- Note that vscode resolves criss-cross folding by taking the higher level folding

See `ipython: Feature Contribution` tab in VSCode Extension (Ctrl + Shift + X)
panel for latest features and details.

If you find the extension useful, it would be awesome if you can leave a comment
and/or a suggestion on GitHub!!
and/or a suggestion on the [project page](https://github.com/hoangKnLai/vscode-ipython/issues)!

- What feature you like and use the most?
- What other feature(s) you would like to have?
Expand All @@ -60,7 +61,7 @@ More on vscode handling of `python` virtual environment can be found in [vscode

[Microsoft Python Extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python)

- This should automatically installed with when this extension is installed
- This should automatically installed when this extension is installed

## Settings

Expand Down Expand Up @@ -91,6 +92,11 @@ Dependent on your project, you might:

## Release Notes

### 2024.1.x

- Added section auto-numbering and manual numbering option to navigator (#48)
- Various efficiency improvement with section handling

### 2023.11.x

- Changed `ipython` command to be compatible with both `Window` and `Linux` (issue #44)
Expand Down
27 changes: 24 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "ipython",
"description": "IPython integration supporting direct interactive usage and commands.",
"icon": "md_img/icon.png",
"version": "2023.11.2",
"version": "2024.1.0",
"publisher": "HoangKimLai",
"repository": {
"type": "git",
Expand Down Expand Up @@ -44,7 +44,25 @@
"javascript",
"markdown"
],
"markdownDescription": "[Language identifier](https://code.visualstudio.com/docs/languages/identifiers) navigator allowed to operates on"
"markdownDescription": "[Language identifier](https://code.visualstudio.com/docs/languages/identifiers) navigator to operates on"
},

"ipython.navigatorTrackingOption": {
"type": "string",
"enum": [
"visible",
"opened"
],
"default": "visible",
"markdownEnumDescriptions": [
"Only show sections of VISIBLE documents of navigatorLanguageId",
"Show sections of ALL opened documents of navigatorLanguageId"
]
},
"ipython.SectionLevelTag": {
"type": "string",
"default": "-",
"markdownDescription": "Indent level tag after a SectionTag like `# %% - Heading 1` to increase heading level by +1"
},
"ipython.SectionTag": {
"type": "array",
Expand Down Expand Up @@ -85,7 +103,10 @@
"%run -i"
],
"default": "%run -i",
"markdownDescription": "(DEPRECATED to just `%run -i` in a future release) Write code block (section, multi-selections) to `{workFolder}/code.py`, then execute using `%run -i or %load code.py`. NOTE: open `code.py` to see exact code executed."
"markdownEnumDescriptions": [
"(DEPRECATED to just `%run -i` in a future release) Use `%load ` to send code to terminal and then execute",
"Write code block (section, multi-selections) to `{workFolder}/code.py`, then execute using `%run -i code.py`. NOTE: open `code.py` to see exact code executed."
]
},
"ipython.RunArguments": {
"type": "string",
Expand Down
22 changes: 13 additions & 9 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ export async function activate(context: vscode.ExtensionContext) {
(item: navi.SectionItem) => {
if (item === undefined) {
console.error('naviRunToSection: found undefined item');
return;
}
if(item && item.position !== undefined && item.document.languageId === 'python'){
ipy.runDocumentSection(item.document, item.position, false);
if(item && item.section !== undefined && item.document.languageId === 'python'){
ipy.runDocumentSection(item.document, item.section, false);
}
},
),
Expand All @@ -57,9 +58,10 @@ export async function activate(context: vscode.ExtensionContext) {
(item: navi.SectionItem) => {
if (item === undefined) {
console.error('naviRunFromSection: found undefined item');
return;
}
if(item && item.position !== undefined && item.document.languageId === 'python'){
ipy.runDocumentSection(item.document, item.position, true);
if(item && item.section !== undefined && item.document.languageId === 'python'){
ipy.runDocumentSection(item.document, item.section, true);
}
},
),
Expand All @@ -69,11 +71,8 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand(
'ipython.naviRunSection',
(item: navi.SectionItem) => {
if (item === undefined) {
console.error('naviRunSection: Found undefined item');
}
if(item && item.position !== undefined && item.document.languageId === 'python'){
ipy.runDocumentSection(item.document, item.position);
if(item && item.section && item.document.languageId === 'python'){
ipy.runDocumentSection(item.document, item.section);
}
},
),
Expand All @@ -82,6 +81,11 @@ export async function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand(
'ipython.naviRunFile',
// (item: navi.SectionTreeItem) => {
// if (item && item.document && item.document.languageId === 'python') {
// ipy.runFile(item.document);
// }
// },
(item: navi.SectionItem) => {
if (item && item.document && item.document.languageId === 'python') {
ipy.runFile(item.document);
Expand Down
127 changes: 72 additions & 55 deletions src/ipython.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function writeCodeFile(filename: string, code: string) {
// === TERMINAL ===

/**
* Format single line or consecutive lines of code to fit ipython terminal.
* Format selected code to fit ipython terminal.
*
* NOTE: always return code with empty newline like newline at end of file.
*
Expand Down Expand Up @@ -567,66 +567,67 @@ export async function runLine() {
/**
* Run current section of python code in an ipython terminal.
* @param document a python text document
* @param cursor a cursor position in document
* @param section of document
* @param toEnd inclusively from top to end of section or from start of section
* to end of file. If undefined, run section at cursor.
* @returns code section that was ran
*/
export async function runDocumentSection(
document: vscode.TextDocument,
cursor: vscode.Position,
section: navi.Section,
toEnd: boolean | undefined = undefined,
) {
let sectionPositions = navi.SECTIONS.get(document.fileName);
if (sectionPositions === undefined) {
console.error('runDocumentSection: failed to retrieve cache');
return;
}
let section = navi.getSectionAt(cursor, sectionPositions, document, false);
if (section === undefined) {
console.error('runDocumentSection: failed to find section');
return;
}

let header = navi.getSectionHeader(
section.start,
document,
);

let startPosition: vscode.Position;
let stopPosition: vscode.Position;
let tag = `${header}`;
let singleSection = toEnd === undefined;
if (singleSection) {
startPosition = section.start;
stopPosition = section.end;
} else { // run to/from section
startPosition = new vscode.Position(0, 0); // beginning of file
stopPosition = section.end;
tag = `run_to: ${header}`;

if (toEnd) { // to bottom
startPosition = section.start;

let lastLine = document.lineAt(document.lineCount - 1);
stopPosition = lastLine.range.end;
tag = `run_from: ${header}`;
}
}
let range = section.range;
let tag = section.name;
runDocumentRange(document, range, tag);
return section.range;
}

if (toEnd) { // to bottom
let lastLine = document.lineAt(document.lineCount - 1);
let range = section.range.with(undefined, lastLine.range.end);
let tag = `run_from: ${section.name}`;
runDocumentRange(document, range, tag);
return section.range;
}

// From top
let beginOfFile = new vscode.Position(0, 0);
let range = section.range.with(beginOfFile);
let tag = `run_to: ${section.name}`;
runDocumentRange(document, range, tag);
return section.range;
}

let sLine = startPosition.line;
let sChar = startPosition.character;
let eLine = stopPosition.line;
let eChar = stopPosition.character;

// NOTE: default line numbering is 1-indexing
// FIXME: consider sourcing it from editor options like tabSize
let lineMarker = `(Line.Col:${sLine + 1}.${sChar}-${eLine + 1}.${eChar})`;
/**
*
* @param document a Python .py text document
* @param range a consecutive set of lines and characters
* @param tag of this run. E.g., `$ %run -i code.py # tag`
* @returns
*/
export async function runDocumentRange(
document: vscode.TextDocument,
range: vscode.Range,
tag: string = '',
) {
if (document.languageId !== 'python') {
console.error(`runDocumentRange: invalid languageId ${document.languageId}`);
return;
}

// let identity = `"# ${tag} ${lineMarker}"`; // in python CLI as a string
let identity = `# ${tag} ${lineMarker}`; // in python CLI as argv
let sLine = range.start.line;
let sChar = range.start.character;
let eLine = range.end.line;
let eChar = range.end.character;
let selectLabel = `(Line.Col:${sLine + 1}.${sChar}-${eLine + 1}.${eChar})`;

let selection = new vscode.Selection(startPosition, stopPosition);
let identity = `# ${tag} ${selectLabel}`; // in python CLI as argv

let selection = new vscode.Selection(range.start, range.end);
let code = formatCode(document, selection);
if (code !== '') {
let terminal = await getTerminal();
Expand All @@ -640,9 +641,9 @@ export async function runDocumentSection(
await executeCodeBlock(terminal, code, identity);
}
}
return section;
}


/**
* Run current section of python code in an ipython terminal.
*
Expand All @@ -658,19 +659,23 @@ export async function runSection(isNext: boolean) {
}

let cursor = editor.selection.start;
let section = await runDocumentSection(editor.document, cursor, undefined);
let section = navi.getSectionFrom(editor.document, cursor);
if (section === undefined) {
console.error('runSection: failed to find section');
return;
}
await runDocumentSection(editor.document, section, undefined);

if (isNext && (section !== undefined)) {
let line = section.end.line + 1;
if (isNext) {
section.jumpToNext(editor);
let line = section.range.end.line + 1;
if (line >= editor.document.lineCount) {
line = editor.document.lineCount - 1;
}

let char = editor.document.lineAt(line).firstNonWhitespaceCharacterIndex;

navi.moveAndRevealCursor(editor, line, char);
} else {
console.error('runSection: error finding next section in document');
}
}

Expand Down Expand Up @@ -810,7 +815,13 @@ export function registerCommands(context: vscode.ExtensionContext) {
if (editor) {
let document = editor.document;
let cursor = editor.selection.start;
runDocumentSection(document, cursor, false);
let section = navi.getSectionFrom(
document,
cursor,
);
if (section) {
runDocumentSection(document, section, false);
}
}
},
)
Expand All @@ -823,7 +834,13 @@ export function registerCommands(context: vscode.ExtensionContext) {
if (editor) {
let document = editor.document;
let cursor = editor.selection.start;
runDocumentSection(document, cursor, true);
let section = navi.getSectionFrom(
document,
cursor,
);
if (section) {
runDocumentSection(document, section, true);
}
}
},
)
Expand Down
Loading