DEV Community

Marco Trulla
Marco Trulla

Posted on • Edited on

A Comment Divider for Zed using Nushell

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-line flag 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)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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",
  }
]
Enter fullscreen mode Exit fullscreen mode

You will need to adjust the path to the script being sourced.

How to Use It

  1. Select the text you want to transform into a comment.
  2. Press Alt+Shift+T to open the task list.
  3. 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
// ===========================================================================
Enter fullscreen mode Exit fullscreen mode

Header Single Line and Sub-header Single Line

//                              THIS IS A COMMENT
Enter fullscreen mode Exit fullscreen mode

Header Filled

// ===========================================================================
// ===========================  THIS IS A COMMENT  ===========================
// ===========================================================================
Enter fullscreen mode Exit fullscreen mode

Header Filled Single Line

// ============================ THIS IS A COMMENT ============================
Enter fullscreen mode Exit fullscreen mode

Sub-header

// ---------------------------------------------------------------------------
//                              THIS IS A COMMENT
// ---------------------------------------------------------------------------
Enter fullscreen mode Exit fullscreen mode

Sub-header Filled

// ---------------------------------------------------------------------------
// ---------------------------  THIS IS A COMMENT  ---------------------------
// ---------------------------------------------------------------------------
Enter fullscreen mode Exit fullscreen mode

Sub-header Filled Single Line

// ---------------------------- THIS IS A COMMENT ----------------------------
Enter fullscreen mode Exit fullscreen mode

Comment Divider

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Enter fullscreen mode Exit fullscreen mode

Multi-lines Comment Header

// ===========================================================================
//                            THIS IS A MULTI-LINE
//                               COMMENT HEADER
//                          WITH THREE LINES OF TEXT
// ===========================================================================
Enter fullscreen mode Exit fullscreen mode

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)