The Uncompromising Nix Code Formatter
4 | 5 | ## Features 6 | 7 | This extension adds built-in editor support 8 | for formatting Nix files automatically 9 | with [Alejandra](https://github.com/kamadorueda/alejandra). 10 | 11 | ## Getting started 12 | 13 | 1. Make sure to install 14 | [Alejandra](https://github.com/kamadorueda/alejandra) 15 | in your system first 16 | as explained [here](https://github.com/kamadorueda/alejandra). 17 | 18 | 1. Install the vscode extension and reload the window (just close and open again). 19 | 20 | 1. Open a Nix file, 21 | do a right click 22 | and you should be able to see "Format Document" in the menu. 23 | 24 | Alternatively, it will be formatted automatically when you save the file. 25 | 26 | Enjoy! 27 | 28 | ## Troubleshooting 29 | 30 | If you encounter a problem 31 | please let us know in the 32 | [issues section](https://github.com/kamadorueda/alejandra/issues). 33 | 34 | The most probable causes of failure are: 35 | 36 | - Not having Alejandra installed in your system. 37 | 38 | In this case please follow the instructions 39 | [here](https://github.com/kamadorueda/alejandra). 40 | 41 | - A misconfiguration. 42 | 43 | In this case please make sure that your config contains the following values: 44 | 45 | ```json 46 | { 47 | "[nix]": { 48 | "editor.defaultFormatter": "kamadorueda.alejandra", 49 | "editor.formatOnPaste": true, 50 | "editor.formatOnSave": true, 51 | "editor.formatOnType": false 52 | }, 53 | "alejandra.program": "alejandra" 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /integrations/vscode/extension.js: -------------------------------------------------------------------------------- 1 | const { execFile } = require("child_process"); 2 | const vscode = require("vscode"); 3 | 4 | const activate = (_) => { 5 | const outputChannel = vscode.window.createOutputChannel("Alejandra"); 6 | 7 | vscode.languages.registerDocumentFormattingEditProvider("nix", { 8 | provideDocumentFormattingEdits(document, _) { 9 | const config = { 10 | alejandra: vscode.workspace.getConfiguration("alejandra"), 11 | }; 12 | 13 | return new Promise((resolve, reject) => { 14 | try { 15 | outputChannel.appendLine( 16 | `Running Alejandra with settings: ${JSON.stringify(config)}` 17 | ); 18 | 19 | const process = execFile( 20 | config.alejandra.program, 21 | [], 22 | {}, 23 | (error, stdout, stderr) => { 24 | if (error) { 25 | outputChannel.appendLine(`error: ${error}`); 26 | outputChannel.appendLine(`stderr: ${stderr}`); 27 | vscode.window.showErrorMessage( 28 | `While executing Alejandra with settings: ` + 29 | `${JSON.stringify(config)}, ` + 30 | `${error}` 31 | ); 32 | reject(error); 33 | } 34 | 35 | const documentRange = new vscode.Range( 36 | document.lineAt(0).range.start, 37 | document.lineAt( 38 | document.lineCount - 1 39 | ).rangeIncludingLineBreak.end 40 | ); 41 | 42 | resolve([new vscode.TextEdit(documentRange, stdout)]); 43 | } 44 | ); 45 | 46 | const documentText = document.getText(); 47 | 48 | outputChannel.appendLine( 49 | `Feeding ${documentText.length} of input to stdin` 50 | ); 51 | 52 | process.stdin.write(documentText); 53 | process.stdin.end(); 54 | } catch (error) { 55 | vscode.window.showErrorMessage( 56 | `While executing Alejandra with settings: ` + 57 | `${JSON.stringify(config)} ` + 58 | `${error}` 59 | ); 60 | reject(error); 61 | } 62 | }); 63 | }, 64 | }); 65 | }; 66 | 67 | const deactivate = () => {}; 68 | 69 | module.exports = { 70 | activate, 71 | deactivate, 72 | }; 73 | -------------------------------------------------------------------------------- /integrations/vscode/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "checkJs": true, 4 | "lib": ["ES2020"], 5 | "module": "CommonJS", 6 | "target": "ES2020" 7 | }, 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /integrations/vscode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "activationEvents": [ 3 | "onLanguage:nix" 4 | ], 5 | "author": { 6 | "email": "kamadorueda@gmail.com", 7 | "name": "Kevin Amado", 8 | "url": "https://github.com/kamadorueda" 9 | }, 10 | "categories": [ 11 | "Formatters" 12 | ], 13 | "contributes": { 14 | "configuration": { 15 | "properties": { 16 | "alejandra.program": { 17 | "default": "alejandra", 18 | "description": "Specifies an alternative full path to the Alejandra executable.", 19 | "type": [ 20 | "string" 21 | ] 22 | } 23 | }, 24 | "title": "Alejandra" 25 | }, 26 | "configurationDefaults": { 27 | "[nix]": { 28 | "editor.defaultFormatter": "kamadorueda.alejandra", 29 | "editor.formatOnPaste": true, 30 | "editor.formatOnSave": true, 31 | "editor.formatOnType": false 32 | }, 33 | "alejandra.program": "alejandra" 34 | }, 35 | "languages": [ 36 | { 37 | "aliases": [ 38 | "nix", 39 | "Nix" 40 | ], 41 | "extensions": [ 42 | ".nix" 43 | ], 44 | "id": "nix" 45 | } 46 | ] 47 | }, 48 | "description": "The Uncompromising Nix Code Formatter", 49 | "devDependencies": { 50 | "ovsx": "*", 51 | "vsce": "*" 52 | }, 53 | "displayName": "Alejandra 💅", 54 | "engines": { 55 | "vscode": "^1.64.0" 56 | }, 57 | "funding": { 58 | "type": "patreon", 59 | "url": "https://www.patreon.com/kamadorueda" 60 | }, 61 | "license": "Unlicense", 62 | "main": "./extension.js", 63 | "name": "alejandra", 64 | "publisher": "kamadorueda", 65 | "repository": { 66 | "type": "git", 67 | "url": "https://github.com/kamadorueda/alejandra" 68 | }, 69 | "version": "4.0.0" 70 | } 71 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # https://github.com/kamadorueda/machine/blob/main/nixos-modules/editor/rustfmt.toml 2 | edition = "2021" 3 | enum_discrim_align_threshold = 999 4 | # force_multiline_blocks = true 5 | format_code_in_doc_comments = true 6 | format_generated_files = true 7 | format_macro_bodies = true 8 | format_macro_matchers = true 9 | format_strings = true 10 | group_imports = "StdExternalCrate" 11 | hex_literal_case = "Lower" 12 | imports_granularity = "Item" 13 | imports_layout = "Vertical" 14 | # match_block_trailing_comma = true 15 | max_width = 80 16 | normalize_comments = true 17 | normalize_doc_attributes = true 18 | overflow_delimited_expr = true 19 | reorder_impl_items = true 20 | struct_field_align_threshold = 999 21 | unstable_features = true 22 | use_field_init_shorthand = true 23 | use_small_heuristics = "Max" 24 | style_edition = "2021" 25 | wrap_comments = true 26 | -------------------------------------------------------------------------------- /src/alejandra/Cargo.toml: -------------------------------------------------------------------------------- 1 | [dependencies] 2 | rnix = { version = "*", default-features = false, features = [] } 3 | rowan = { version = "0.15.16", default-features = false, features = [] } 4 | serde = { version = "*", default-features = false, features = ["derive"] } 5 | 6 | [target.aarch64-unknown-linux-musl.dependencies.mimalloc] 7 | default-features = false 8 | version = "0" 9 | 10 | [target.arm-unknown-linux-musleabihf.dependencies.mimalloc] 11 | default-features = false 12 | version = "0" 13 | 14 | [target.i686-unknown-linux-musl.dependencies.mimalloc] 15 | default-features = false 16 | version = "0" 17 | 18 | [target.x86_64-unknown-linux-gnu.dependencies.mimalloc] 19 | default-features = false 20 | version = "0" 21 | 22 | [target.x86_64-unknown-linux-musl.dependencies.mimalloc] 23 | default-features = false 24 | version = "0" 25 | 26 | [package] 27 | authors = ["Kevin Amado