├── .gitignore
├── images
├── icon.png
├── readme_1.gif
└── readme_2.gif
├── .vscodeignore
├── jsconfig.json
├── .eslintrc.json
├── test
├── extension.test.js
└── index.js
├── LICENSE
├── CHANGELOG.md
├── README.md
├── vsc-extension-quickstart.md
├── extension.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .vscode-test/
3 | *.vsix
4 | .vscode/
5 |
--------------------------------------------------------------------------------
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgesbert/vscode-python-path/HEAD/images/icon.png
--------------------------------------------------------------------------------
/images/readme_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgesbert/vscode-python-path/HEAD/images/readme_1.gif
--------------------------------------------------------------------------------
/images/readme_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgesbert/vscode-python-path/HEAD/images/readme_2.gif
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | test/**
4 | .gitignore
5 | jsconfig.json
6 | vsc-extension-quickstart.md
7 | .eslintrc.json
8 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "checkJs": false,
6 | "lib": ["es6"]
7 | },
8 | "exclude": ["node_modules"]
9 | }
10 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": false,
4 | "commonjs": true,
5 | "es6": true,
6 | "node": true
7 | },
8 | "parserOptions": {
9 | "ecmaFeatures": {
10 | "jsx": true
11 | },
12 | "sourceType": "module"
13 | },
14 | "rules": {
15 | "no-const-assign": "warn",
16 | "no-this-before-super": "warn",
17 | "no-undef": "warn",
18 | "no-unreachable": "warn",
19 | "no-unused-vars": "warn",
20 | "constructor-super": "warn",
21 | "valid-typeof": "warn"
22 | }
23 | }
--------------------------------------------------------------------------------
/test/extension.test.js:
--------------------------------------------------------------------------------
1 | /* global suite, test */
2 |
3 | //
4 | // Note: This example test is leveraging the Mocha test framework.
5 | // Please refer to their documentation on https://mochajs.org/ for help.
6 | //
7 |
8 | // The module 'assert' provides assertion methods from node
9 | const assert = require('assert');
10 |
11 | // You can import and use all API from the 'vscode' module
12 | // as well as import your extension to test it
13 | // const vscode = require('vscode');
14 | // const myExtension = require('../extension');
15 |
16 | // Defines a Mocha test suite to group tests of similar kind together
17 | suite("Extension Tests", function() {
18 |
19 | // Defines a Mocha unit test
20 | test("Something 1", function() {
21 | assert.equal(-1, [1, 2, 3].indexOf(5));
22 | assert.equal(-1, [1, 2, 3].indexOf(0));
23 | });
24 | });
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | //
2 | // PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
3 | //
4 | // This file is providing the test runner to use when running extension tests.
5 | // By default the test runner in use is Mocha based.
6 | //
7 | // You can provide your own test runner if you want to override it by exporting
8 | // a function run(testRoot: string, clb: (error:Error) => void) that the extension
9 | // host can call to run the tests. The test runner is expected to use console.log
10 | // to report the results back to the caller. When the tests are finished, return
11 | // a possible error to the callback or null if none.
12 |
13 | const testRunner = require('vscode/lib/testrunner');
14 |
15 | // You can directly control Mocha options by uncommenting the following lines
16 | // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
17 | testRunner.configure({
18 | ui: 'tdd', // the TDD UI is being used in extension.test.js (suite, test, etc.)
19 | useColors: true // colored output from test results
20 | });
21 |
22 | module.exports = testRunner;
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Mathias Gesbert
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## 0.0.14 (2022-08-10)
4 |
5 | ### Fixed
6 |
7 | - **license:** fixed license name
8 |
9 | ## 0.0.13 (2022-08-10)
10 |
11 | ### Added
12 |
13 | - **license:** added MIT license
14 |
15 | ## 0.0.12 (2022-08-10)
16 |
17 | ### Bug Fixes
18 |
19 | - **clipboard:** remove dependency to clipboardy, use vscode env clipboard
20 |
21 | ## 0.0.11 (2019-04-04)
22 |
23 | ### Improvements
24 |
25 | - **logo:** new version
26 |
27 |
28 |
29 | ## 0.0.10 (2019-02-25)
30 |
31 | ### Bug Fixes
32 |
33 | - **config:** categories + keywords
34 |
35 | ### Improvements
36 |
37 | - **logo:** outline for white background context
38 |
39 |
40 |
41 | ## 0.0.9 (2019-02-20)
42 |
43 | ### Bug Fixes
44 |
45 | - **syntax:** avoid generating import statements when selecting text which is not a valid variable name
46 |
47 | ### Improvements
48 |
49 | - **logo:** white text
50 |
51 |
52 |
53 | ## 0.0.8 (2019-02-19)
54 |
55 | ### Bug Fixes
56 |
57 | - **syntax:** avoid generating import statements when selecting text which contains "\n"
58 |
59 | ### Improvements
60 |
61 | - **logo:** add transparency
62 |
63 |
64 |
65 | ## 0.0.5 (2018-11-26)
66 |
67 | ### Bug Fixes
68 |
69 | - **syntax:** Fix path splitting on Windows
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Python Path
2 |
3 | This extension adds a set of tools which help you generate internal import statements in a python project.
4 |
5 | ## Features
6 |
7 | "Copy Python Path" is accessible from:
8 |
9 | - Command
10 | - Explorer contextual menu
11 | - Editor contextual menu
12 | - Editor title contextual menu
13 |
14 | ### Basic Copy Python Path
15 |
16 | Copies the full module name of the current file to the clipboard.
17 |
18 | 
19 |
20 | ### Generate import statement
21 |
22 | Copies an import statement for the selected text to the clipboard.
23 | In case of a simple selection, the generated statement will be:
24 |
25 | ```
26 | from module.name import selected_text
27 | ```
28 |
29 | In case of a multiple selection, the generated statement will be:
30 |
31 | ```
32 | from module.name import (
33 | selected_text_1,
34 | selected_text_2,
35 | [...]
36 | selected_text_n,
37 | )
38 | ```
39 |
40 | 
41 |
42 | ## Miscellaneous
43 |
44 | Inspiration from the Sublime Package: https://github.com/pokidovea/copy_python_path
45 |
46 | ## Credits
47 |
48 | - https://github.com/mgesbert
49 | - https://github.com/nfau
50 |
--------------------------------------------------------------------------------
/vsc-extension-quickstart.md:
--------------------------------------------------------------------------------
1 | # Welcome to your VS Code Extension
2 |
3 | ## What's in the folder
4 | * This folder contains all of the files necessary for your extension.
5 | * `package.json` - this is the manifest file in which you declare your extension and command.
6 | The sample plugin registers a command and defines its title and command name. With this information
7 | VS Code can show the command in the command palette. It doesn’t yet need to load the plugin.
8 | * `extension.js` - this is the main file where you will provide the implementation of your command.
9 | The file exports one function, `activate`, which is called the very first time your extension is
10 | activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
11 | We pass the function containing the implementation of the command as the second parameter to
12 | `registerCommand`.
13 |
14 | ## Get up and running straight away
15 | * Press `F5` to open a new window with your extension loaded.
16 | * Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`.
17 | * Set breakpoints in your code inside `extension.js` to debug your extension.
18 | * Find output from your extension in the debug console.
19 |
20 | ## Make changes
21 | * You can relaunch the extension from the debug toolbar after changing code in `extension.js`.
22 | * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
23 |
24 | ## Explore the API
25 | * You can open the full set of our API when you open the file `node_modules/vscode/vscode.d.ts`.
26 |
27 | ## Run tests
28 | * Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Launch Tests`.
29 | * Press `F5` to run the tests in a new window with your extension loaded.
30 | * See the output of the test result in the debug console.
31 | * Make changes to `test/extension.test.js` or create new test files inside the `test` folder.
32 | * By convention, the test runner will only consider files matching the name pattern `**.test.js`.
33 | * You can create folders inside the `test` folder to structure your tests any way you want.
34 |
--------------------------------------------------------------------------------
/extension.js:
--------------------------------------------------------------------------------
1 | const vscode = require("vscode");
2 | const fs = require("fs");
3 | const path = require("path");
4 |
5 | function getPythonPath(filePath) {
6 | const splittedPath = filePath.split(path.sep);
7 | if (
8 | splittedPath.length === 0 ||
9 | !splittedPath[splittedPath.length - 1].endsWith(".py")
10 | ) {
11 | return "";
12 | }
13 |
14 | const fileName = splittedPath.pop();
15 |
16 | // removing extension
17 | let pythonPath =
18 | fileName !== "__init__.py"
19 | ? [fileName.substring(0, fileName.lastIndexOf("."))]
20 | : [];
21 |
22 | while (
23 | splittedPath.length > 0 &&
24 | fs.existsSync([...splittedPath, ["__init__.py"]].join(path.sep))
25 | ) {
26 | pythonPath.unshift(splittedPath.pop());
27 | }
28 |
29 | return pythonPath.join(".");
30 | }
31 |
32 | function copyPythonPath(uri) {
33 | try {
34 | const filePath = uri
35 | ? uri.fsPath
36 | : vscode.window.activeTextEditor.document.fileName;
37 | const pythonPath = getPythonPath(filePath);
38 | const selections = vscode.window.activeTextEditor.selections
39 | .map(s => vscode.window.activeTextEditor.document.getText(s))
40 | .filter(s => !!s && !s.includes("\n") && !s.trim().includes(" "));
41 | if (pythonPath && selections.length > 0) {
42 | const importStatement = generateImportStatement(pythonPath, selections);
43 | vscode.env.clipboard.writeText(importStatement);
44 | }
45 | if (pythonPath && selections.length == 0) {
46 | vscode.env.clipboard.writeText(pythonPath);
47 | }
48 | } catch (e) {
49 | console.log(e);
50 | }
51 | }
52 |
53 | function generateImportStatement(pythonPath, selections) {
54 | if (selections.length == 0) {
55 | return `import ${pythonPath}`;
56 | } else if (selections.length == 1) {
57 | const selection = selections[0].trim();
58 | return `from ${pythonPath} import ${selection}`;
59 | }
60 | const selection = selections.map(s => `\t${s.trim()},`).join("\n");
61 | return `from ${pythonPath} import (\n${selection}\n)`;
62 | }
63 |
64 | function activate(context) {
65 | let disposable = vscode.commands.registerCommand(
66 | "extension.copyPythonPath",
67 | copyPythonPath
68 | );
69 | context.subscriptions.push(disposable);
70 | }
71 |
72 | exports.activate = activate;
73 |
74 | function deactivate() {}
75 | exports.deactivate = deactivate;
76 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "activationEvents": [
3 | "onLanguage:python",
4 | "onCommand:extension.copyPythonPath",
5 | "onCommand:extension.generateImportStatement"
6 | ],
7 | "author": {
8 | "name": "Mathias Gesbert"
9 | },
10 | "categories": [
11 | "Programming Languages",
12 | "Snippets",
13 | "Formatters",
14 | "Other",
15 | "Extension Packs"
16 | ],
17 | "contributes": {
18 | "commands": [
19 | {
20 | "command": "extension.copyPythonPath",
21 | "title": "Copy Python Path",
22 | "when": "resourceLangId == python"
23 | }
24 | ],
25 | "menus": {
26 | "editor/context": [
27 | {
28 | "command": "extension.copyPythonPath",
29 | "group": "9_cutcopypaste@30000",
30 | "title": "Copy Python Path",
31 | "when": "resourceLangId == python"
32 | }
33 | ],
34 | "editor/title/context": [
35 | {
36 | "command": "extension.copyPythonPath",
37 | "group": "1_cutcopypaste@30000",
38 | "title": "Copy Python Path",
39 | "when": "resourceLangId == python"
40 | }
41 | ],
42 | "explorer/context": [
43 | {
44 | "command": "extension.copyPythonPath",
45 | "group": "5_cutcopypaste@30000",
46 | "title": "Copy Python Path",
47 | "when": "resourceLangId == python"
48 | }
49 | ]
50 | }
51 | },
52 | "contributors": [
53 | "Nicolas Faurie"
54 | ],
55 | "description": "Python imports utils.",
56 | "devDependencies": {
57 | "@types/mocha": "^2.2.42",
58 | "@types/node": "^7.0.43",
59 | "eslint": "^4.11.0",
60 | "typescript": "^2.6.1",
61 | "vscode": "^1.1.6"
62 | },
63 | "displayName": "Python Path",
64 | "engines": {
65 | "vscode": "^1.22.0"
66 | },
67 | "galleryBanner": {
68 | "color": "#1e415e",
69 | "theme": "dark"
70 | },
71 | "icon": "images/icon.png",
72 | "keywords": [
73 | "import",
74 | "export",
75 | "python",
76 | "generator"
77 | ],
78 | "main": "./extension",
79 | "name": "python-path",
80 | "publisher": "mgesbert",
81 | "repository": {
82 | "type": "git",
83 | "url": "https://github.com/mgesbert/vscode-python-path.git"
84 | },
85 | "scripts": {
86 | "postinstall": "node ./node_modules/vscode/bin/install",
87 | "test": "node ./node_modules/vscode/bin/test"
88 | },
89 | "version": "0.0.14"
90 | }
91 |
--------------------------------------------------------------------------------