Like many of you, I recently switched from VS Code to Zed. Despite having a few limitations compared to the "programming behemoth," I absolutely love it. It’s fast, reliable, and packed with useful features.
However, there is always a "but." Occasionally, I miss specific extensions from my VS Code configuration. One such example is the small but helpful Comment Divider extension, which allows you to select text and convert it into a stylized comment block.
Since Zed doesn't have an equivalent extension yet, I decided to replicate the functionality using Nushell (my daily shell of choice).
Note: I primarily use Arch Linux on WSL, so you may need to adjust the code slightly (specifically the clipboard command) to suit your environment.
1. The Nushell Script
First, I created a command to generate the comments. You can save this as a standalone script or place it in your $nu.user-autoload-dir to ensure it's sourced at startup.
UPDATE 2026-01-07: add the
--single-lineflag to generate single line comments.
# Generate a comment into the style of a specified programming language.
@example 'Generate a header comment for C, 80 chars width, centered' { comment generate "THIS IS A HEADER" }
@example 'Generate a sub-header comment Python, 75 chars width, centered' { comment generate "THIS IS A SUB-HEADER" -l py -w 75 -s sub-header }
def "comment generate" [
text: string = '' # text of the comment; it can be multilines
--language (-l): string = 'c' # language
--width (-w): int = 80
--align (-a): string = 'center'
--style (-s): string = 'header' # header, sub-header, divider
--filled (-f) # fill the spaces
--single-line (-S) # single line comment
--list
] {
const C_STYLE_LANGUAGES = [c cpp c3 d js ts jsonc]
const BASH_STYLE_LANGAUGES = [sh nu py]
if $list {
$C_STYLE_LANGUAGES | append $BASH_STYLE_LANGAUGES | sort
} else {
const SAFETY_MARGIN = 2
let comment_symbol = match $language {
$lang if $lang in $C_STYLE_LANGUAGES => { '//' }
$lang if $lang in $BASH_STYLE_LANGAUGES => { '#' }
_ => { '//' }
}
let real_width = $width - $SAFETY_MARGIN - ($comment_symbol | str length) - 1
match $style {
"header" => {
const char = '='
let filler = if $filled { $char } else { ' ' }
if not $single_line {
($comment_symbol + ' ' + ('' | fill -w $real_width -c $char) + (char newline) +
($text | lines | each {$comment_symbol + ' ' + ($in | fill -w $real_width -a $align -c $filler) } | str join (char newline)) + (char newline) +
$comment_symbol + ' ' + ('' | fill -w $real_width -c $char) + (char newline)
)
} else {
$comment_symbol + ' ' + ($text | fill -w $real_width -a $align -c $filler) + (char newline)
}
}
"sub-header" => {
const char = '-'
let filler = if $filled { $char } else { ' ' }
if not $single_line {
($comment_symbol + ' ' + ('' | fill -w $real_width -c $char) + (char newline) +
($text | lines | each {$comment_symbol + ' ' + ($in | fill -w $real_width -a $align -c $filler) } | str join (char newline)) + (char newline) +
$comment_symbol + ' ' + ('' | fill -w $real_width -c $char) + (char newline)
)
} else {
$comment_symbol + ' ' + ($text | fill -w $real_width -a $align -c $filler) + (char newline)
}
}
"divider" => {
const char = '~'
$comment_symbol + ' ' + ('' | fill -w $real_width -c $char) + (char newline)
}
}
}
}
2. Configuring Zed Tasks
The next step is to add a task in Zed to trigger this command. Open your tasks configuration by pressing Ctrl+Shift+P (or Cmd+Shift+P on Mac) and searching for zed: open tasks. Add the following JSON:
UPDATE 2016-01-07: add tasks for single line comments
[
{
"label": "Comment Header",
"command": "source ($nu.user-autoload-dirs.0)/commands.nu ; comment generate \"$ZED_SELECTED_TEXT\" -l (\"$ZED_FILENAME\" | path parse | get extension) | wl-copy",
"hide": "on_success",
},
{
"label": "Comment Header Single Line",
"command": "source ($nu.user-autoload-dirs.0)/commands.nu ; comment generate \"$ZED_SELECTED_TEXT\" -l (\"$ZED_FILENAME\" | path parse | get extension) -S | wl-copy",
"hide": "on_success",
},
{
"label": "Comment Sub-header",
"command": "source ($nu.user-autoload-dirs.0)/commands.nu ; comment generate \"$ZED_SELECTED_TEXT\" -l (\"$ZED_FILENAME\" | path parse | get extension) -s sub-header | wl-copy",
"hide": "on_success",
},
{
"label": "Comment Sub-header Single Line",
"command": "source ($nu.user-autoload-dirs.0)/commands.nu ; comment generate \"$ZED_SELECTED_TEXT\" -l (\"$ZED_FILENAME\" | path parse | get extension) -s sub-header -S | wl-copy",
"hide": "on_success",
},
{
"label": "Comment Divider",
"command": "source ($nu.user-autoload-dirs.0)/commands.nu ; comment generate \"$ZED_SELECTED_TEXT\" -l (\"$ZED_FILENAME\" | path parse | get extension) -s divider | wl-copy",
"hide": "on_success",
},
{
"label": "Comment Header Filled",
"command": "source ($nu.user-autoload-dirs.0)/commands.nu ; comment generate \"$ZED_SELECTED_TEXT\" -l (\"$ZED_FILENAME\" | path parse | get extension) -f | wl-copy",
"hide": "on_success",
},
{
"label": "Comment Header Filled Single Line",
"command": "source ($nu.user-autoload-dirs.0)/commands.nu ; comment generate \"$ZED_SELECTED_TEXT\" -l (\"$ZED_FILENAME\" | path parse | get extension) -S -f | wl-copy",
"hide": "on_success",
},
{
"label": "Comment Sub-header Filled",
"command": "source ($nu.user-autoload-dirs.0)/commands.nu ; comment generate \"$ZED_SELECTED_TEXT\" -l (\"$ZED_FILENAME\" | path parse | get extension) -s sub-header -f | wl-copy",
"hide": "on_success",
},
{
"label": "Comment Sub-header Filled Single Line",
"command": "source ($nu.user-autoload-dirs.0)/commands.nu ; comment generate \"$ZED_SELECTED_TEXT\" -l (\"$ZED_FILENAME\" | path parse | get extension) -s sub-header -S -f | wl-copy",
"hide": "on_success",
}
]
You will need to adjust the path to the script being sourced.
How to Use It
- Select the text you want to transform into a comment.
- Press
Alt+Shift+Tto open the task list. - Select your desired comment style and press Enter.
The task will generate the formatted comment and copy it to your clipboard (I haven't found a way to inject it directly at the cursor position yet). Simply paste it over your selection, and you're good to go!
Examples
Header
// ===========================================================================
// THIS IS A COMMENT
// ===========================================================================
Header Single Line and Sub-header Single Line
// THIS IS A COMMENT
Header Filled
// ===========================================================================
// =========================== THIS IS A COMMENT ===========================
// ===========================================================================
Header Filled Single Line
// ============================ THIS IS A COMMENT ============================
Sub-header
// ---------------------------------------------------------------------------
// THIS IS A COMMENT
// ---------------------------------------------------------------------------
Sub-header Filled
// ---------------------------------------------------------------------------
// --------------------------- THIS IS A COMMENT ---------------------------
// ---------------------------------------------------------------------------
Sub-header Filled Single Line
// ---------------------------- THIS IS A COMMENT ----------------------------
Comment Divider
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Multi-lines Comment Header
// ===========================================================================
// THIS IS A MULTI-LINE
// COMMENT HEADER
// WITH THREE LINES OF TEXT
// ===========================================================================
Known Limitations
- Manual Injection: As mentioned previously, there is currently no way to inject the text directly into the editor. You must rely on an external clipboard command to copy and paste the result.
- File Naming: The command "guesses" the language style by reading the file extension. Therefore, the file must be saved with a filename; it will not work on "Untitled" buffers.
Top comments (0)