<!--
  canonical-url: https://www.avonture.be/blog/vscode-regions
  published:     2024-08-05
  This is a static plain-Markdown mirror generated at build time.
  Visit the canonical URL above for the fully rendered page, with images and interactive components.
-->

# Working with regions in VSCode

> Master code folding in VSCode with regions. Learn how to use them in PHP and how to enable region support for unsupported files like Dockerfile with a simple extension.

---
![Working with regions in VSCode](/img/v2/vscode_tips.webp)

**TL;DR**

This article shows how to use `region`/`endregion` folding tags in VSCode (e.g. in PHP) to collapse logical blocks of code, and how to add that same folding support to files VSCode doesn't handle natively, like a Dockerfile, using the `maptz.regionfolder` extension plus a `.vscode/settings.json` entry. It also mentions the `Auto Fold` extension for automatically collapsing regions when a file is opened.

VSCode supports `region` and `endregion` tags but not everywhere. These two special tags can be written differently depending on the language you're using but always have the same objective: to allow you to fold part of the code.

Not everywhere means, for instance, that VSCode doesn't support code folding by default in a Dockerfile. Let's see how to solve this.

*A well-folded file is one thing; a well-organized one is another. For Bash, [Linux - Sort functions in a Bash script](/blog/linux-sort-functions-in-script) checks that your functions are declared in a predictable order.*

## Regions in action

![VSCode - Regions folding](./images/regions.gif)

That's what `region`/`endregion` tags buy you: entire logical blocks collapse to a single line,
so you see the structure of a file instead of scrolling through it.

## Code folding in PHP

Consider the following, very basic, example (*very brief example for illustrative purposes*):

**my\_class.php**

```php
<?php

class MyClass
{
    public function onContentPrepare()
    {
        $query = $this->db->getQuery(true);
        $query->select('note');
        $query->from('#__content_ratings');
        $query->where('content_id = 8');

        $this->db->setQuery($query);
        $notes = $this->db->loadColumn();

        return $notes;
    }
}
```

We can clearly identify three blocks: preparation of the query, run it and return the data. Using regions, we can do this — the two lines shown above (`// #region`, `// #endregion`) are what produce the fold/unfold behavior in the gif:

**my\_class.php**

```php
<?php

class MyClass
{
    public function onContentPrepare()
    {
        //region 1. Prepare the SQL query
        $query = $this->db->getQuery(true);
        $query->select('note');
        $query->from('#__content_ratings');
        $query->where('content_id = 8');
        //endregion

        //region 2. Run the query
        $this->db->setQuery($query);
        $notes = $this->db->loadColumn();
        //endregion

        //region 3. Prepare resulting array
        return $notes;
        //endregion
    }
}
```

> **You should avoid having functions having more than 60 lines:**
>
> Regions are supported by a very large number of languages, but don't make the mistake of assuming that this allows you to have functions of several dozen lines. That's not the point!  If you have long functions, you need to split them up. You need to create smaller, more specialised functions. We've already touched on this point in a [previous post](/blog/vscode-php-refactoring).

## What to do when VSCode didn't support these tags by default?

Let's take a look and the following Dockerfile:

**Dockerfile**

```docker
# syntax=docker/dockerfile:1

# Source https://docusaurus.community/knowledge/deployment/docker/?package-managers=yarn

ARG HOMEDIR=/opt/docusaurus
ARG TARGET=/development

# The user and group ID of the user to create
ARG DOCKER_UID=1000
ARG DOCKER_GID=1000
ARG USERNAME=christophe

# Stage 1: Base image.

FROM node:lts AS base

# Disable color output from yarn to make logs easier to read.
ENV FORCE_COLOR=0

# Enable corepack.
RUN corepack enable

ARG TARGET
RUN /bin/bash -c "echo \"PS1='\n\e[0;33m🐳 (${TARGET})\e[0m - \e[0;36m$(whoami)\e[0m \w # '\" >> ~/.bashrc "

# --------------------------------------------------------------------

# Stage 2a: Development mode.

FROM base AS development

ARG HOMEDIR

RUN apt-get -y update \
    && apt-get install --yes --no-install-recommends git \
    && git config --global --add safe.directory ${HOMEDIR} \
    && rm -rf /var/lib/apt/lists/*

# We'll create a new user with the same uid/gid than ours, on our host machine.
ARG DOCKER_UID
ARG DOCKER_GID
ARG USERNAME

# hadolint ignore=DL3008
RUN set -e -x \
    && if [ ! "$DOCKER_UID" = "1000" ]; then \
    groupadd --gid ${DOCKER_GID} "${USERNAME}" \
    && useradd --home-dir /home/"${USERNAME}" --create-home --uid ${DOCKER_UID} \
        --gid ${DOCKER_GID} --shell /bin/sh --skel /dev/null "${USERNAME}" ; \
    fi

USER "${USERNAME}"

# Set the working directory to `/opt/docusaurus`.
WORKDIR "${HOMEDIR}"

# --------------------------------------------------------------------

# Stage 2b: Production build mode.

FROM base AS building_production

ARG TARGET

# Target is set in the .env file to "development" or "production"
ENV NODE_ENV="${TARGET}"

# Install the latest version of Docusaurus
ARG HOMEDIR
RUN npx create-docusaurus@latest "${HOMEDIR}/" classic --javascript \
    # Remove dummy files like dummy blog, docs, ... that were added during the installation
    && rm -rf "${HOMEDIR}/blog" "${HOMEDIR}/docs" "${HOMEDIR}/src" \
    && chown -R node:node "${HOMEDIR}/"

# Set the working directory to `/opt/docusaurus`.
WORKDIR "${HOMEDIR}"

# We need our package.json / package.lock file before running yarn install
COPY package.* .

# Install dependencies with `--immutable` to ensure reproducibility.
RUN yarn install --immutable

# Copy over the source code.
COPY . "${HOMEDIR}/"

# Build the static site (generated files will be created in /opt/docusaurus/build)
RUN yarn build

# --------------------------------------------------------------------

# Stage 3: Serve with nginx

FROM nginx:stable-alpine3.19-perl AS production

RUN set -e -x; \
    apk update --no-cache && apk add --no-cache bash \
    && rm -rf /var/cache/apk/*

ARG TARGET

RUN /bin/sh -c "echo \"PS1='\n\e[0;33m🐳 (${TARGET})\e[0m - \e[0;36m$(whoami)\e[0m \w # '\" >> ~/.bashrc "

# Copy the Docusaurus build output.
ARG HOMEDIR

COPY --from=building_production "${HOMEDIR}/build /usr/share/nginx/html"

WORKDIR /usr/share/nginx/html
```

Opening such a file in VSCode doesn't provide any collapse/expand features and we will need to scroll a lot. And we don't have a global overview of the structure.

![No region support in VSCode for Dockerfile](./images/dockerfile-before.webp)

The solution comes by installing a specialised extension: <https://marketplace.visualstudio.com/items?itemName=maptz.regionfolder>.

And, too, by adding these settings in your `.vscode/settings.json` file:

**.vscode/settings.json**

```json
{
    "maptz.regionfolder": {
        "[dockerfile]": {
            "foldEnd": "\\# endregion",
            "foldEndRegex": "\\# endregion[\\s]*(.*)$",
            "foldStart": "\\# region [NAME],",
            "foldStartRegex": "\\# region[\\s]*(.*)$"
        }
    }
}
```

Switch back to your tab in VSCode with your opened Dockerfile, press `CTRL`+`P` and run `Developer: Reload Window` to reload the window once the extension has been enabled and tadaaa!

![Now, VSCode supports regions in Dockerfile](./images/dockerfile-after.webp)

> **No, it's not just a visual trick:**
>
> When you're working on very long files like, for me, a Dockerfile of over 900 lines, it's really imperative to be able to have regions that you can reduce/expand.
>
> Not only does this make it easier to read, it also facilitates the succession of 'stages' (when programming a multistage Dockerfile).

## Auto fold extension

There are some extensions like [Auto Fold](https://marketplace.visualstudio.com/items?itemName=bobmagicii.autofoldyeah) that can automatically fold regions when opening a file.

The idea is: when you open a file with a lot of methods, all functions are first *folded* (we just see the function name, not its content). That way you can directly see the structure of the file, the list of functions and so on without having to scroll much.

If you install [Auto Fold](https://marketplace.visualstudio.com/items?itemName=bobmagicii.autofoldyeah), you also need to add the `"autofold.default": 1,` setting in your `settings.json` file.

If you don't know how, just press `CTRL`+`,` (the comma) to display the `Settings` page then start to type `autofold` to get access to the setting.

Now, if you open a file, its content will be automatically folded.

![Autofold](./images/autofold.webp)

## Conclusion

Two tags, `// #region` and `// #endregion` (adapted to your language's comment syntax), are all
it takes to fold any block of code — native in most languages, and easy to bolt onto the ones
VSCode doesn't support out of the box, like a Dockerfile.
