<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Garage XP]]></title><description><![CDATA[Garage XP]]></description><link>https://blog.jeremyfiel.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 21 May 2026 07:25:40 GMT</lastBuildDate><atom:link href="https://blog.jeremyfiel.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[ffmpeg: download streams, trim video, concat files]]></title><description><![CDATA[Download individual stream files
ffmpeg -i <input-file> -c <codec> <output-file>

Start with the ffmpeg command
-i = input file
<input-file> either a stream url or local file
-c = codec to be used
<codec>\= I always use copy to use the same codec as ...]]></description><link>https://blog.jeremyfiel.com/ffmpeg-download-streams-trim-video-concat-files</link><guid isPermaLink="true">https://blog.jeremyfiel.com/ffmpeg-download-streams-trim-video-concat-files</guid><category><![CDATA[concat-files]]></category><category><![CDATA[trim-video]]></category><category><![CDATA[FFmpeg]]></category><dc:creator><![CDATA[Jeremy Fiel]]></dc:creator><pubDate>Sat, 07 Jan 2023 16:50:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/ugx-DVSEvBM/upload/f6ca06326cc20fc92e56d638d308014c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-download-individual-stream-files">Download individual stream files</h3>
<pre><code class="lang-bash">ffmpeg -i &lt;input-file&gt; -c &lt;codec&gt; &lt;output-file&gt;
</code></pre>
<p>Start with the <code>ffmpeg</code> command</p>
<p><code>-i</code> = input file</p>
<p><code>&lt;input-file&gt;</code> either a stream url or local file</p>
<p><code>-c</code> = codec to be used</p>
<p><code>&lt;codec&gt;</code>\= I always use <code>copy</code> to use the same codec as the stream, or you can specify any other codec you want</p>
<p><code>&lt;output-file&gt;</code> = the filename you want to save</p>
<h3 id="heading-trim-the-parts-you-dont-want">Trim the parts you don't want</h3>
<pre><code class="lang-bash">ffmpeg -ss &lt;hh:mm:ss&gt; -i &lt;input-file&gt; -to &lt;hh:mm:ss&gt; -c &lt;codec&gt; &lt;output-file&gt;
</code></pre>
<p>Start with the <code>ffmpeg</code> command</p>
<p><code>-ss</code> = start time of the video to trim</p>
<p><code>&lt;hh:mm:ss&gt;</code> = must be in the format of hours:minutes:seconds</p>
<p><code>-i</code> = input file</p>
<p><code>&lt;input-file&gt;</code> either a stream url or local file</p>
<p><code>-to</code> = total length of clip time, this can be confusing at first because you need to calculate the elapsed time of the clip. e.g. If you want to trim a clip that begins at 01:23:33 (one hour, 23 minutes, 33 seconds) and you want the video trimmed to 01:23:55 (one hour, 23 minutes, 55 seconds), the value of <code>to</code> would be <code>00:00:22</code> (22 seconds elapsed time)</p>
<p><code>-c</code> = codec to be used</p>
<p><code>&lt;codec&gt;</code>\= I always use <code>copy</code> to use the same codec as the stream, or you can specify any other codec you want</p>
<p><code>&lt;output-file&gt;</code> = the filename you want to save, make sure you create a copy and don't overwrite the original file you are trimming</p>
<h3 id="heading-save-all-your-files-with-a-consistent-naming-pattern-to-easily-collect-them-for-future-use">Save all your files with a consistent naming pattern to easily collect them for future use</h3>
<pre><code class="lang-bash"><span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> &lt;pattern&gt;; <span class="hljs-keyword">do</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"file '<span class="hljs-variable">$f</span>'"</span> &gt;&gt; &lt;output-file&gt;; <span class="hljs-keyword">done</span>
</code></pre>
<p>let's write a bash script to easily create a playlist of the files you want to concat</p>
<p><code>for &lt;variable&gt; in</code> is a bash loop to find all instances of the pattern given</p>
<p><code>f</code> is a variable name for "file", it could be anything</p>
<p><code>&lt;pattern&gt;</code> is a regex pattern of the filename e.g. <code>*title-mm-dd-yy*</code></p>
<p><code>do</code> begins the looping process</p>
<p><code>echo "file '$f'"</code> tells bash to write the text <code>"file &lt;filename&gt;"</code> from the variable <code>f</code> to stdout (the terminal)</p>
<p><code>&gt;&gt;</code> is a direction operator in Linux to write a file. When two arrows are present, it signifies append to the existing file</p>
<p><code>&lt;output-file&gt;</code> should be a text file e.g. <code>files.txt</code></p>
<p><code>&lt;semi-colon&gt;</code> is used to end the previous command</p>
<p>we need to finish with a <code>done</code> command to finish the loop</p>
<p>This will create a <code>files.txt</code> with a playlist of the matching files</p>
<blockquote>
<p>file 'game-01-01-23_1.mp4'</p>
<p>file 'game-01-01-23_2.mp4'</p>
<p>file 'game-01-01-23_3.mp4'</p>
<p>file 'game-01-01-23_4.mp4'</p>
</blockquote>
<h3 id="heading-concat-your-files">Concat your files</h3>
<pre><code class="lang-bash">ffmpeg -f concat -i &lt;input-file&gt; -safe 0 -c &lt;codec&gt; &lt;output-file&gt;
</code></pre>
<p>Start with the <code>ffmpeg</code> command</p>
<p><code>-f</code>\= indicates to ffmpeg to list each file for concatenation</p>
<p><code>concat</code> = concatenate command</p>
<p><code>-i</code> = input file</p>
<p><code>&lt;input-file&gt;</code> either a stream url or local file</p>
<p><code>-safe 0</code> = dictates unsafe file names should be ignored, this is mainly used to allow relative paths</p>
<p><code>-c</code> = codec to be used</p>
<p><code>&lt;codec&gt;</code>\= I always use <code>copy</code> to use the same codec as the stream, or you can specify any other codec you want</p>
<p><code>&lt;output-file&gt;</code> = the filename you want to save, make sure you create a copy and don't overwrite the original files you are using to create the final version</p>
]]></content:encoded></item><item><title><![CDATA[Bitbucket: Pull PR and commit local changes to remote forks]]></title><description><![CDATA[As a maintainer of a very large repo, we ask our developers to use the Forking Workflow
This has some challenges, especially when reviewing PRs and committing changes to those PRs on the respective, remote forks.
After many months and lots of blog re...]]></description><link>https://blog.jeremyfiel.com/bitbucket-pull-pr-and-commit-local-changes-to-remote-forks</link><guid isPermaLink="true">https://blog.jeremyfiel.com/bitbucket-pull-pr-and-commit-local-changes-to-remote-forks</guid><category><![CDATA[Bitbucket]]></category><category><![CDATA[Pull Requests]]></category><category><![CDATA[Git]]></category><category><![CDATA[remote]]></category><category><![CDATA[refspec]]></category><dc:creator><![CDATA[Jeremy Fiel]]></dc:creator><pubDate>Tue, 13 Dec 2022 23:59:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670992170096/hpnBVQHjh.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a maintainer of a very large repo, we ask our developers to use the <a target="_blank" href="https://www.atlassian.com/git/tutorials/comparing-workflows/forking-workflow#:~:text=Forking%20is%20a%20git%20clone,org%2FuserA%2Fopen%2Dproject">Forking Workflow</a></p>
<p>This has some challenges, especially when reviewing PRs and committing changes to those PRs on the respective, remote forks.</p>
<p>After many months and lots of blog reading, <a target="_blank" href="https://git-scm.com/book/en/v2/Git-Internals-The-Refspec">git-scm.org - The Refspec</a> review and trial and error, I think I finally figured out the best way to work with this forking strategy.</p>
<p>First things first, set your refspecs to pull down all the PRs to the main repo. I picked this up from <a target="_blank" href="https://www.atlassian.com/git/articles/pull-request-proficiency-fetching-abilities-unlocked">Atlassian's blog - Pull Request Proficiency</a>.</p>
<p>I went about it slightly differently from their post but it works just as well and it was fewer steps.</p>
<p>Add a <code>git config</code> for <code>remote.origin.fetch</code>
This adds a local namespace so you can eventually checkout a pr with shorthand</p>
<pre><code class="lang-bash">git config add remote.origin.fetch +refs/pull-requests/*:refs/remotes/origin/pr/*
</code></pre>
<p><code>git pull origin &lt;main branch&gt;</code> or whichever branch you are receiving the PRs</p>
<pre><code class="lang-bash"> git pull origin develop
remote: Enumerating objects: 501, <span class="hljs-keyword">done</span>.
remote: Counting objects: 100% (326/326), <span class="hljs-keyword">done</span>.
remote: Compressing objects: 100% (229/229), <span class="hljs-keyword">done</span>.
remote: Total 248 (delta 170), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (248/248), 54.99 KiB | 1.37 MiB/s, <span class="hljs-keyword">done</span>.
Resolving deltas: 100% (170/170), completed with 42 <span class="hljs-built_in">local</span> objects.
From ssh://bitbucket.&lt;your-domain&gt;.com:&lt;port&gt;/&lt;project&gt;/&lt;repo&gt;
 * branch                  develop                      -&gt; FETCH_HEAD
 * [new ref]               refs/pull-requests/1472/from -&gt; origin/pr/1472/from
 * [new ref]               refs/pull-requests/1473/from -&gt; origin/pr/1473/from
 * [new ref]               refs/pull-requests/1474/from -&gt; origin/pr/1474/from
 * [new ref]               refs/pull-requests/1475/from -&gt; origin/pr/1475/from
 * [new ref]               refs/pull-requests/1477/from -&gt; origin/pr/1477/from
</code></pre>
<p>Now you can checkout the PR on your local machine with <code>git checkout origin/pr/1474/from</code></p>
<pre><code class="lang-bash">git checkout origin/pr/1474/from
Note: switching to <span class="hljs-string">'origin/pr/1474/from'</span>.

You are <span class="hljs-keyword">in</span> <span class="hljs-string">'detached HEAD'</span> state. You can look around, make experimental
changes and commit them, and you can discard any commits you make <span class="hljs-keyword">in</span> this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
<span class="hljs-keyword">do</span> so (now or later) by using -c with the switch <span class="hljs-built_in">command</span>. Example:

  git switch -c &lt;new-branch-name&gt;

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to <span class="hljs-literal">false</span>

HEAD is now at &lt;commit&gt; fix spec validations
</code></pre>
<p>Now you're free to poke around, make changes, and commit changes to your local detached HEAD state</p>
<p>You'll notice here, git reminds you that you are in <code>detached HEAD</code> state on commit.</p>
<pre><code class="lang-bash">git commit -m <span class="hljs-string">"&lt;commit message title&gt;"</span> -m <span class="hljs-string">"    &lt;commit message body&gt;[APIDESGN-1367]"</span>
[detached HEAD &lt;commit&gt;] feat(api): update event-notifications schema
 7 files changed, 32 insertions(+), 384 deletions(-)
 delete mode 100644 &lt;some-file-named-you-modified&gt;
</code></pre>
<p>-- You <em>ARE</em> using &lt;issue-keys&gt; in your commit messages, RIGHT?!?!</p>
<p>Now comes the fun part, setting up the remote fork and pushing your local changes to the PR. Add a new <code>remote</code> and name it whatever you want. This is the fork where the PR originated. I usually use the PR number as the remote to remind me of the PR number</p>
<pre><code class="lang-bash">git remote add 1474 ssh://git@bitbucket.&lt;your-domain&gt;.com:&lt;port&gt;/&lt;project&gt;/&lt;repo&gt;.git
</code></pre>
<p>You can run <code>git remote -vv</code> to see all of your remote configs</p>
<pre><code class="lang-bash">git remote -vv
1474    ssh://git@bitbucket.&lt;your-domain&gt;:&lt;port&gt;/&lt;fork-project&gt;/&lt;repo&gt;.git (fetch)
1474    ssh://git@bitbucket.&lt;your-domain&gt;:&lt;port&gt;/&lt;fork-project&gt;/&lt;repo&gt;.git (push)
origin  ssh://git@bitbucket.&lt;your-domain&gt;:&lt;port&gt;/&lt;main-project&gt;/&lt;repo&gt;.git (fetch)
origin  ssh://git@bitbucket.&lt;your-domain&gt;:&lt;port&gt;/&lt;main-project&gt;/&lt;repo&gt;.git (push)
</code></pre>
<p>Now you can run <code>git branch</code> and notice you have the <code>HEAD detached</code> and your <code>develop</code> branch. (you may have additional branches)</p>
<pre><code class="lang-bash">git branch
* (HEAD detached from origin/pr/1474/from)
  develop
</code></pre>
<p>It's time to <code>fetch</code> the upstream repo to pull down the actual branch name on the remote fork</p>
<pre><code class="lang-bash"> git fetch 1474
remote: Enumerating objects: 54, <span class="hljs-keyword">done</span>.
remote: Counting objects: 100% (54/54), <span class="hljs-keyword">done</span>.
remote: Compressing objects: 100% (52/52), <span class="hljs-keyword">done</span>.
remote: Total 60 (delta 28), reused 1 (delta 1), pack-reused 6
Unpacking objects: 100% (60/60), 16.54 KiB | 127.00 KiB/s, <span class="hljs-keyword">done</span>.
From ssh://bitbucket.&lt;your-domain&gt;:&lt;port&gt;/&lt;fork-project&gt;/&lt;repo&gt;
 * [new branch]            develop    -&gt; 1474/develop
 * [new branch]            feature/APIDESGN-1367-&lt;branch-name&gt; -&gt; 1474/feature/APIDESGN-1367-&lt;branch-name&gt;
</code></pre>
<p>Now we know the name of the original branch from the fork, we can <code>checkout</code> and <code>merge</code> our new commits. Since I've committed changes to the detached HEAD, I need to merge that commit into the branch. You can work in detached HEAD state or you can work on the actual branch, I just happened to make some changes while poking around in detached state. The beauty of checking out the branch in this fashion is git automatically sets the new branch to track the upstream branch, which is linked to the original PR</p>
<pre><code class="lang-bash"> git checkout feature/APIDESGN-1367-&lt;branch-name&gt;
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

  &lt;commit&gt; feat(api): update event-notifications schema

If you want to keep it by creating a new branch, this may be a good time
to <span class="hljs-keyword">do</span> so with:

 git branch &lt;new-branch-name&gt; &lt;commit&gt;

Switched to a new branch <span class="hljs-string">'feature/APIDESGN-1367-&lt;branch-name&gt;'</span>
branch <span class="hljs-string">'feature/APIDESGN-1367-&lt;branch-name&gt;'</span> <span class="hljs-built_in">set</span> up to track <span class="hljs-string">'1474/feature/APIDESGN-1367-&lt;branch-name&gt;'</span>.
</code></pre>
<p>Checking <code>git branch -vv</code> once more indicates the new branch is tracking the upstream we defined as <code>1474</code></p>
<pre><code class="lang-bash">git branch -vv
  develop                                    &lt;commit&gt; &lt;commit-message&gt;
* feature/APIDESGN-1367-&lt;branch-name&gt; &lt;commit&gt; [1474/feature/APIDESGN-1367-&lt;branch-name&gt;] fix spec validations
</code></pre>
<p>I opted not to create a new branch as suggested by the git cli but rather <code>merge</code> my previous commit on the detached HEAD to the branch we just checked out</p>
<pre><code class="lang-bash">git merge &lt;commit-from-detached-head&gt;
Updating &lt;commit&gt;..&lt;commit&gt;
Fast-forward
 ...&lt;some-modified-files&gt;     | 104 +---------
 7 files changed, 32 insertions(+), 384 deletions(-)
</code></pre>
<p>Now we are ready to push our local changes to the upstream remote fork, but first let's check the status to see where we are. Oh look! Git recognizes we are now 1 commit ahead of our upstream remote fork branch</p>
<pre><code class="lang-bash">git status
On branch feature/APIDESGN-1367-&lt;branch-name&gt;
Your branch is ahead of <span class="hljs-string">'1474/feature/APIDESGN-1367-&lt;branch-name&gt;'</span> by 1 commit.
  (use <span class="hljs-string">"git push"</span> to publish your <span class="hljs-built_in">local</span> commits)
</code></pre>
<p>OK, let's push! We use the upstream remote name and the branch name to tell git where we want to go and where the changes were made</p>
<pre><code class="lang-bash">git push 1474 feature/APIDESGN-1367-&lt;branch-name&gt;
Enumerating objects: 24, <span class="hljs-keyword">done</span>.
Counting objects: 100% (24/24), <span class="hljs-keyword">done</span>.
Delta compression using up to 8 threads
Compressing objects: 100% (12/12), <span class="hljs-keyword">done</span>.
Writing objects: 100% (13/13), 1.44 KiB | 491.00 KiB/s, <span class="hljs-keyword">done</span>.
Total 13 (delta 8), reused 0 (delta 0), pack-reused 0
remote:
remote: View pull request <span class="hljs-keyword">for</span> feature/APIDESGN-1367-&lt;branch-name&gt; =&gt; develop:
remote:   https://bitbucket.&lt;your-domain&gt;.com/projects/&lt;project&gt;/repos/&lt;repo&gt;/pull-requests/1474
remote:
To ssh://bitbucket.&lt;your-domain&gt;.com:&lt;port&gt;/&lt;project&gt;/&lt;repo&gt;.git
   &lt;commit&gt;..&lt;commit&gt;  feature/APIDESGN-1367-&lt;branch-name&gt; -&gt; feature/APIDESGN-1367-&lt;branch-name&gt;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Find all commits related to a specific file path]]></title><description><![CDATA[Every now and then a bug is introduced with a new file added to the repo. How do we track down when this file was first committed and any additional commits to this file along the way?  There are many, many ways of doing this in git. One of those way...]]></description><link>https://blog.jeremyfiel.com/find-all-commits-related-to-a-specific-file-path</link><guid isPermaLink="true">https://blog.jeremyfiel.com/find-all-commits-related-to-a-specific-file-path</guid><category><![CDATA[git log]]></category><dc:creator><![CDATA[Jeremy Fiel]]></dc:creator><pubDate>Mon, 06 Jun 2022 19:57:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/GM9Xpgb0g98/upload/v1654542042745/bVxdzmpUW.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every now and then a bug is introduced with a new file added to the repo. How do we track down when this file was first committed and any additional commits to this file along the way?  There are many, <em>many</em> ways of doing this in git. One of those ways is to use <code>git log --follow</code>:</p>
<pre><code class="lang-sh">git <span class="hljs-built_in">log</span> --follow --name-only -p &lt;file&gt;
</code></pre>
<ul>
<li><code>git log</code>: is the command to view the history of the entire repo</li>
<li><code>--follow</code>: allows us to "follow" the commit history of a specific file including where a file was renamed</li>
<li><code>--name-only</code>: allows us to trim the commit message output to only view the file names and metadata associated with the commit message rather than the complete diff</li>
<li><code>-p</code>: indicates the file path to search for</li>
</ul>
<p>Using <a target="_blank" href="https://www.github.com/freeCodecamp">freeCodeCamp</a> Open Source project gives us the following when searching for the Hall Of Fame (HoF.md) file. </p>
<p><code>git log</code> lists commits in reverse chronological order: (newest first)</p>
<p>Here you can see the file:</p>
<ul>
<li>created Feb 6, 2020</li>
<li>updated on Feb 8, 2020</li>
<li>updated again on Mar 18, 2020.</li>
</ul>
<pre><code class="lang-sh">// using a relative path of the root folder freeCodeCamp to find HoF.md

$ git <span class="hljs-built_in">log</span> --follow --name-only -p <span class="hljs-string">'./HoF.md'</span>

commit 7613df56e1736ae6c53fac3eaedc3570cdb636a9
Author: mrugesh &lt;1884376+raisedadead@users.noreply.github.com&gt;
Date:   Wed Mar 18 06:23:56 2020 +0530

    chore: add Peter-Samir to HOF (<span class="hljs-comment">#38384)</span>

    Co-authored-by: Peter-Samir &lt;43256727+Peter-Samir@users.noreply.github.com&gt;

HoF.md

commit 9e1bac4807d0268c561bb8ddad84fffac8ee07e1
Author: mrugesh &lt;1884376+raisedadead@users.noreply.github.com&gt;
Date:   Sat Feb 8 21:12:19 2020 +0530

    docs: update hall of fame verbiage

HoF.md

commit 158188924b9281f2afe5332c7804ddcd058137c9
Author: Mehul Mohan &lt;mehulmpt@gmail.com&gt;
Date:   Thu Feb 6 18:14:20 2020 +0530

    docs: added responsible disclosure and hall of fame

HoF.md
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Search and Replace Quoted Strings in YAML]]></title><description><![CDATA[Regex capture groups and bash positional arguments to replace text in VS Code
I've been knee deep in OpenAPI specs in my current role as an API Product Manager. While the work is fulfilling, there are some very mundane aspects to onboarding a develop...]]></description><link>https://blog.jeremyfiel.com/search-and-replace-quoted-strings-in-yaml</link><guid isPermaLink="true">https://blog.jeremyfiel.com/search-and-replace-quoted-strings-in-yaml</guid><category><![CDATA[YAML]]></category><category><![CDATA[Visual Studio Code]]></category><category><![CDATA[Regex]]></category><category><![CDATA[search]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Jeremy Fiel]]></dc:creator><pubDate>Thu, 06 Jan 2022 20:33:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/yoyWQ0P1t7Y/upload/v1641491681508/4BOspWgIA9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-regex-capture-groups-and-bash-positional-argumentshttpswwwgnuorgsoftwarebashmanualhtmlnodepositional-parametershtml-to-replace-text-in-vs-code">Regex capture groups and bash <a target="_blank" href="https://www.gnu.org/software/bash/manual/html_node/Positional-Parameters.html">positional arguments</a> to replace text in VS Code</h2>
<p>I've been knee deep in <a target="_blank" href="https://openapis.org">OpenAPI</a> specs in my current role as an API Product Manager. While the work is fulfilling, there are some very mundane aspects to onboarding a development team when using the OpenAPI specification; particularly, the formatting of YAML documents. There is a wonderful <em>readability</em> aspect to working with YAML when certain behaviors are adhered to. Without getting into the firestorm of using single quote ('), double quote (") or no quotes, you can read more about that <a target="_blank" href="https://stackoverflow.com/a/69850618/8564731">here</a>, I find myself reviewing several documents where our development team are diverging from each other in the way they are documenting our API's. Certainly, there is a selfish aspect of wanting consistency while reviewing these documents. I have 1000's of specs to review for our internal developer ecosystem and I'm trying my best to automate as much review work as possible.</p>
<p>Ok, let's get to it: 
I have documents exceeding 10-thousand lines of code and there are 100's of enumerations throughout. I needed a quick and easy way to clean up the excessive quotes wrapping enum strings because it looks <em>hideous</em>! </p>
<p>Typically, I'm reviewing OpenAPI docs in VS Code because first and foremost, it's my favorite editor, and secondly, the plethora of extensions for making my life easy to read 10-thousand line documents. </p>
<p>some of my faves: 
<a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow">Indent-Rainbow</a>
<a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=stoplight.spectral">Spectral API Linter</a>
<a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode">Prettier</a></p>
<p>Start with <code>ctrl + f</code> / <code>cmd + f</code> and select the <code>.*</code> icon, or toggle regex with <code>alt + r</code> / <code>cmd + r</code></p>
<p>There is probably some caveat here about using <code>example(s)</code> in OpenAPI because there are a few different ways to represent them, depending on the version. I'm using <code>example</code> at the schema level which means we don't have any representation of an <code>array</code> example which can be overwritten by my regex.</p>
<p>We start with an OpenAPI document similar to our Animal example: </p>
<pre><code class="lang-yaml"><span class="hljs-attr">openapi:</span> <span class="hljs-number">3.0</span><span class="hljs-number">.3</span>
<span class="hljs-attr">info:</span>
  <span class="hljs-attr">description:</span> <span class="hljs-string">This</span> <span class="hljs-string">is</span> <span class="hljs-string">a</span> <span class="hljs-string">great</span> <span class="hljs-string">representation</span> <span class="hljs-string">of</span> <span class="hljs-string">an</span> <span class="hljs-string">Animal</span>
  <span class="hljs-attr">version:</span> <span class="hljs-string">'1.0.0'</span>
  <span class="hljs-attr">title:</span> <span class="hljs-string">Animal</span>
  <span class="hljs-attr">contact:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">'jeremy'</span>
    <span class="hljs-attr">email:</span> <span class="hljs-string">'hola@jeremyfiel.com'</span>
<span class="hljs-attr">paths:</span>
    <span class="hljs-string">/endpoint:</span>
      <span class="hljs-attr">get:</span>
         <span class="hljs-string">...</span>
<span class="hljs-attr">components:</span>
  <span class="hljs-attr">schemas:</span>
    <span class="hljs-attr">Animal:</span>
      <span class="hljs-attr">description:</span> <span class="hljs-string">Some</span> <span class="hljs-string">type</span> <span class="hljs-string">of</span> <span class="hljs-string">living</span> <span class="hljs-string">creature</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">object</span>
      <span class="hljs-attr">required:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">breed</span>
      <span class="hljs-attr">properties:</span>
        <span class="hljs-attr">breed:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
          <span class="hljs-attr">enum:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'GERMAN SHEPARD'</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'BEAGLE'</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">'RETRIEVER'</span>
          <span class="hljs-attr">example:</span> <span class="hljs-string">'BEAGLE'</span>
</code></pre>
<p>I'm looking for any representation of an enumeration in the file. </p>
<p>The formatting is:</p>
<ul>
<li>any line starting with spaces or tabs</li>
<li>eventually a <code>-</code></li>
<li>followed by a single space to indicate the array of enumerations available.</li>
<li>Then, I'm expecting a string wrapped in some form of quotes.</li>
</ul>
<pre><code class="lang-js"> ^(\s+-\s)  (<span class="hljs-string">'|"|`)  (\w+((\s|-)+\w+)*)  ('</span>|<span class="hljs-string">"|`)$
 ^---1---^  ^--2--^  ^--------3--------^ ^--4--^

Capture Groups:
  one: starts with any number of spaces or tabs, a dash and exactly one following space
  two: finds any type of quote. single('), double("</span>), backtick (<span class="hljs-string">`)
  three: finds any word representation, including spaces, underscore, or hyphens
  four: finds any type of quote. single('), double("), backtick (`</span>)
</code></pre>
<p>VS Code uses <a target="_blank" href="https://github.com/BurntSushi/ripgrep">ripgrep</a> as their regex search engine, so we are able to use <a target="_blank" href="https://www.gnu.org/software/bash/manual/html_node/Positional-Parameters.html">positional arguments</a> provided by the bash scripting engine. This is why I've split the regex into capture groups. Each capture group is returned as a separate argument and we can utilize these arguments to replace our enum strings <strong>without</strong> the <em>ugly</em> quotes.</p>
<p>The arguments follow a numbering sequence and can be called directly in the <code>replace text</code> field.</p>
<p>If we were to look at the argument sequence, it breaks down like this:</p>
<ul>
<li><code>$0</code> is equivalent to the <em>first match</em> of the entire <code>find</code> command. In our case, the result of the regex pattern we used to search <code>......- 'GERMAN SHEPARD'</code></li>
<li><code>$1</code> is the indentation, dash and single space before the string <code>......-</code></li>
<li><code>$2</code> is the first set of quotes <code>'</code></li>
<li><code>$3</code> is our enum string <code>GERMAN SHEPARD</code></li>
<li><code>$4</code> is the final set of quotes <code>'</code></li>
</ul>
<p>Now we can use these arguments to replace the text without the quotes.</p>
<p><img src="https://user-images.githubusercontent.com/32110157/148439075-4d628f81-954b-4f3e-881c-98a81acf9500.png" alt="VS Code Find &amp; Replace dialogue" /></p>
<pre><code class="lang-js">$<span class="hljs-number">1</span>$<span class="hljs-number">3</span>

   $<span class="hljs-number">1</span> holds the first capture group which is <span class="hljs-string">"        - "</span>.  This is the indentation and dash 
   $<span class="hljs-number">3</span> holds the third capture group which is our enum string *without* quotes.
</code></pre>
<p>Viola! </p>
<pre><code class="lang-yaml">
      <span class="hljs-attr">properties:</span>
        <span class="hljs-attr">breed:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
          <span class="hljs-attr">enum:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">GERMAN</span> <span class="hljs-string">SHEPARD</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">BEAGLE</span>
            <span class="hljs-bullet">-</span> <span class="hljs-string">RETREIVER</span>
          <span class="hljs-attr">example:</span> <span class="hljs-string">'BEAGLE'</span>
</code></pre>
<p>It's so beautiful!! Now I can get back to reviewing my documents without stabbing my eyeballs with a bunch of ugly quotes. </p>
<p>If you like tips like these, let me know! </p>
]]></content:encoded></item></channel></rss>