<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <title>Blog entries tagged vim :: mwop.net</title>
    <description>Blog entries tagged vim :: mwop.net</description>
    <pubDate>Tue, 19 Dec 2023 12:14:00 -0600</pubDate>
    <generator>Laminas_Feed_Writer 2 (https://getlaminas.org)</generator>
    <link>https://mwop.net/blog/tag/vim</link>
    <atom:link rel="self" type="application/rss+xml" href="https://mwop.net/blog/tag/vim/rss.xml"/>
    <item>
      <title>Advent 2023: (n)vim Plugins: vim-markdown</title>
      <pubDate>Tue, 19 Dec 2023 12:14:00 -0600</pubDate>
      <link>https://mwop.net/blog/2023-12-19-advent-vim-markdown.html</link>
      <guid>https://mwop.net/blog/2023-12-19-advent-vim-markdown.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>I'm a huge fan of <a href="https://www.markdownguide.org/">Markdown</a>.
There's something elegant in using textual sigils to provide contextual information.
I've used it for taking notes, creating RSS feed content, producing my blog, and even in emails (I soooo wish there were a way to convert markdown within Outlook for the web and GMail!)</p>
<p>So it should come as no surprise that I use a variety of tools to help me when writing markdown in (n)vim.</p>


<h3>What are the tools?</h3>
<p>The <a href="https://github.com/aareman/vim-markdown">aareman/vim-markdown</a> plugin provides the core functionality, and features syntax highlighting.
What's great is that in a terminal that supports it, you'll actually see things appear in bold, italics, or underlined.
Headers, links, and monospace text each get a different color, and sometimes even weight.</p>
<p>From there, I have a number of other plugins that augment the functionality from vim-markdown:</p>
<ul>
<li><a href="dhruvasagar/vim-table-mode">vim-table-mode</a> provides on-the-fly autoformatting of textual tables, including those in Markdown.
This is invaluable, as it allows me to see <em>as I type</em> if I'm missing columns, adding extra columns, etc.</li>
<li><a href="https://github.com/img-paste-devs/img-paste.vim">img-paste.vim</a> allows pasting a screenshot into a markdown document.
It will copy the screenshot to a specified relative directory, and then create the markup for displaying it in the document.</li>
<li><a href="https://github.com/vim-pandoc/vim-pandoc-syntax">vim-pandoc-syntax</a> does much of the heavy lifting for syntax highlighting, particularly when it comes to fenced code blocks.
If you use <a href="https://github.github.com/gfm/">Github Flavored Markdown</a>, you can optionally specify a <em>language</em> when creating a fenced code block; vim-pandoc-syntax will identify the language, and use it to provide syntax highlighting within the code block for the given language.</li>
</ul>
<p>Additionally, with <a href="/blog/2023-12-17-advent-vim-coc.html">coc.nvim</a>, I get integration with <a href="https://github.com/markdownlint/markdownlint">markdownlint</a>, which flags potential syntax and style issues.</p>
<h3>How I configure it</h3>
<p>I configure vim-markdown using the following:</p>
<pre><code class="language-vimrc">let g:markdown_disable_folding            = 1
let g:markdown_disable_motions            = 0
let g:markdown_disable_spell_checking     = 0
let g:markdown_disable_conceal            = 0
let g:markdown_disable_table_mode         = 0
let g:markdown_disable_pandoc_integration = 0
let g:markdown_disable_clean_empty_on_cr  = 0

nnoremap &lt;buffer&gt; &lt;Leader&gt;x :call markdown#SwitchStatus()&lt;CR&gt;
</code></pre>
<p>These do the following:</p>
<ul>
<li>I rarely use code folding, and when I do, I want to do it manually.
As such, I disable auto-folding done by the plugin.</li>
<li>vim-markdown provides a variety of <em>motions</em> that let you jump around more quickly in a markdown document, particularly to the previous header (<code>[[</code>) or the next header (<code>]]</code>).
I want to keep these around.</li>
<li>Spell checking is nice.</li>
<li>&quot;conceal&quot; will <em>conceal</em> markup sigils when you're not on a line; the terminal continues to highlight them appropriately (e.g. bold, italic, underlined, etc.).
Links are collapsed to just the highlighted linked text, collapsing the content around them.
Doing this makes <em>reading</em> the document easier; when you're on the line, it will reveal all concealed characters so you can edit.</li>
<li>Table mode enables the integration with vim-table-mode; I definitely want this.</li>
<li>Pandoc integration enables the pandoc syntax highlighting; I definitely want this.</li>
<li>If I hit Enter from a list item, it creates a new list item.
This last setting means that I can hit Enter again, and it will clear the list item and start a line below.
It's an easy way to end a list and start typing the next paragraph.</li>
<li>I often use GFM checkboxes for TODO lists. The mapping declaration maps <code>&lt;Leader&gt;x</code> to toggle the checkbox.</li>
</ul>
<h3>Final thoughts</h3>
<p>After <a href="/blog/2023-12-15-advent-vim-surround.html">vim-surround</a> and <a href="/blog/2023-12-17-advent-vim-coc.html">coc.nvim</a>, this is undoubtedly the plugin that gives me the most value.
I benefited from it <em>typing up this very blog post</em>!
While a GUI IDE can provide side-by-side editing where you can see how the Markdown is transformed, I rarely need that; the whole point of Markdown is to provide a <em>human readable</em> format that provides <em>contextual markup</em>.
Reading the raw file should be enough.</p>
<p>vim-markdown gives me the ability to have a raw Markdown file, while simultaneously giving me just enough visual context to understand things even when skimming a document.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2023-12-19-advent-vim-markdown.html">Advent 2023: (n)vim Plugins: vim-markdown</a> was originally
    published <time class="dt-published" datetime="2023-12-19T12:14:00-06:00">19 December 2023</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Advent 2023: (n)vim Plugins: vim-fugitive</title>
      <pubDate>Mon, 18 Dec 2023 15:34:00 -0600</pubDate>
      <link>https://mwop.net/blog/2023-12-18-advent-vim-fugitive.html</link>
      <guid>https://mwop.net/blog/2023-12-18-advent-vim-fugitive.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>Because I've spent most of my professional life coding, I've also spent a lot of time using source control.
I've been using specifically <a href="https://git-scm.com/">git</a> for many years (even pre-dating the Zend Framework migration from <a href="https://subversion.apache.org">Subversion</a>).
While I typically use a terminal multiplexer (for me, that's <a href="https://github.com/tmux/tmux/wiki">tmux</a>; for others, that might be <a href="https://www.gnu.org/software/screen/">screen</a>), and can move to another pane or create one quickly in order to run source control commands, doing so interrupts flow.</p>
<p>That's where <a href="https://github.com/tpope/vim-fugitive">vim-fugitive</a> comes into play.</p>


<h3>What does it solve?</h3>
<p>Fugitive integrates with git, plain and simple.
It exposes a number of commands and functions that allow you to do common operations quickly, but also has some deeper bindings to allow doing more complex things such as viewing a file from previous commits, or performing a diff between the staged and working version, or using <code>git blame</code> within vim.</p>
<h3>How do I use it?</h3>
<p>Admittedly, I use a very small subset of what Fugitive provides.</p>
<p>On a daily basis, I use <code>:Gwrite</code> to stage changes, and <code>:G</code> to view the status of the working tree.
When in the status view, I often use <code>cc</code> to <strong>c</strong>ommit <strong>c</strong>hanges, which splits open a pane for writing the commit message.
I also use <code>:GRemove</code> when I want to remove a file from the tree.</p>
<p>Something else that has come in handy when reviewing code with others: <code>:GBrowse</code> can open the file in the canonical repository, using the visual selection as the line range, allowing you to quickly share a link to specific code to review.</p>
<h3>Final Thoughts</h3>
<p>This plugin does exactly what it says on the tin.
I love the fact that it integrates with the underlying <code>git</code> command, as that follows the Unix Philosophy of doing one thing well, and piping out to other processes to perform complex behavior.
For me, the fact that I can stay directly within my editor and still get full access to git when needed is tremondously powerful.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2023-12-18-advent-vim-fugitive.html">Advent 2023: (n)vim Plugins: vim-fugitive</a> was originally
    published <time class="dt-published" datetime="2023-12-18T15:34:00-06:00">18 December 2023</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Advent 2023: (n)vim Plugins: coc.nvim</title>
      <pubDate>Sun, 17 Dec 2023 13:32:00 -0600</pubDate>
      <link>https://mwop.net/blog/2023-12-17-advent-vim-coc.html</link>
      <guid>https://mwop.net/blog/2023-12-17-advent-vim-coc.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>I've used vim and variants since 2001.
In 2019, a friend introduced me to <a href="https://github.com/neoclide/coc.nvim">coc.nvim</a>, which turned out to be my initial gateway to nvim, which I adopted a year or two later.</p>


<h3>What is coc.nvim?</h3>
<p>The plugin name is an acronym for &quot;Conquer of Completion&quot;, and its goal is to &quot;Make your Vim/Neovim as smart as VS Code&quot;.
While it can be used with either vim or neovim, it has some optimizations under the hood to allow usage with neovim's <a href="https://neovim.io/doc/user/lsp.html">language server protocol support</a>, which allows it to expose more features and perform better when using that editor.</p>
<p>The language server protocol exposes features like (per the neovim documentation) &quot;go-to-definition, find-references, hover, completion, rename, format, refactor, etc., using semantic whole-project analysis.&quot;</p>
<p>In practice, this means the following:</p>
<ul>
<li>You get signature hints.
In PHP, this will pick up hints from the signature, but also hints from docblocks.</li>
<li>You get completion.
Hitting <code>&lt;Tab&gt;</code>, you'll see a list of possible matches.
<ul>
<li>When in PHP, if the match is for a class name, it will add the import statements for you.</li>
<li>Also in PHP, if the match is for a method that exists in an implemented interface or a parent class, it will complete the signature for you, and perform any imports required.</li>
</ul>
</li>
<li>If your cursor is on something like a property name, a method name, a class name, or more, you can jump to the definition (I have this mapped to <code>gd</code>, for &quot;<strong>g</strong>o to <strong>d</strong>efinition).</li>
<li>Depending on the language server in use, you may also get the ability to do limited refactoring, such as changing a variable/property name throughout a file, or renaming a method and all calls to it.</li>
</ul>
<p>Interestingly enough, the LSP is what is used under-the-hood by IDEs like VS Code, so I'm getting the same features I'd get using a dedicated IDE!</p>
<p>These features helped me so much, I ponied up for an <a href="https://intelephense.com/">Intelephense</a> license.</p>
<h3>If neovim already supports language servers natively, why use coc.nvim?</h3>
<p>I use a variety of languages, and the configuration for each varies widely.
On top of that, when I started using neovim, I wasn't yet familiar with Lua, which is how you configure things like the LSP.
But even once I learned... the documentation for the various LSP implementations is often missing or inscrutable; it's hard to know what options are available, and how to modify the behavior programmatically.</p>
<p>coc.nvim just takes care of it, gives me a single location for configuration, gives me a single set of keybindings to remember, and provides a unified interface for operations like jumping to definitions, performing refactors, and more.</p>
<p>Less futzing, more working.</p>
<h3>Why was this helpful?</h3>
<p>Prior to adopting coc.nvim, I used things like <a href="https://ctags.sourceforge.net/">ctags</a> to provide some limited completion and ability to jump to definitions.
However, this was problematic in that I would forget to regenerate ctags for a project when I added or changed dependencies, as well as when adding my own code; they were always out-of-date.
Using them, I ended up having to keep a mental map in my head of the project, so that I could open the class file with a definition when needing to understand what the signature allowed, or what the method returned.
This approach was fine when I was doing development every day, or working on familiar code bases, but often neither of these are true anymore.</p>
<h3>Why not just use a &quot;real&quot; IDE?</h3>
<p>Listen, IDEs are great.
But even when I've taken time to get to know an IDE, I've found I'm just not as productive when using one.
Vim and its descendants are highly optimized for touch typists, and make movement and selection ridiculously fast compared to using a mouse, trackpad, or visual pointer.</p>
<p>Having tools like coc.nvim allow me to get some of the chief benefits of an IDE from within my preferred editor.
Sure, I don't get advanced refactoring tools, but I can always reach for <a href="https://getrector.com/">Rector</a> when I need to.
Debugging? <a href="https://github.com/vim-vdebug/vdebug">vim-debug</a> gives me most of what I would need, and I can reach for a visual IDE if I need more granular control.</p>
<p>The LSP and coc.nvim give me the best of both worlds: excellent tooling for a touch typist, with IDE features that give contextual information when I need it.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2023-12-17-advent-vim-coc.html">Advent 2023: (n)vim Plugins: coc.nvim</a> was originally
    published <time class="dt-published" datetime="2023-12-17T13:32:00-06:00">17 December 2023</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Advent 2023: (n)vim Plugins: tabular</title>
      <pubDate>Sat, 16 Dec 2023 14:56:00 -0600</pubDate>
      <link>https://mwop.net/blog/2023-12-16-advent-vim-tabular.html</link>
      <guid>https://mwop.net/blog/2023-12-16-advent-vim-tabular.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p><a href="/blog/2023-12-15-advent-vim-surround.html">Yesterday, I discussed vim-surround</a>.
Today I'm going to discuss another plugin I've used a ton: <a href="https://github.com/godlygeek/tabular">tabular</a>.</p>


<h3>What problem does it solve?</h3>
<p>Let's say you have a PHP associative array declaration:</p>
<pre><code class="language-php hljs php" data-lang="php">[
    <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Matthew"</span>,
    <span class="hljs-string">"status"</span> =&gt; <span class="hljs-string">"online"</span>,
    <span class="hljs-string">"url"</span> =&gt; <span class="hljs-string">"https://mwop.net"</span>
]
</code></pre>
<p>Now, for some folks, this declaration is fine.
However, I tend to prefer aligning the declarations, as it helps me visually parse the block more easily.</p>
<p>Now, I could go to each line, and insert space before the <code>=&gt;</code> assignment operators.
This works, and for a short declaration like in this example, it's relatively quick.
But when the declaration is larger, or the sizes of the keys vary a lot, this can become tedious quickly.</p>
<p>Another place I've used it is Markdown tables:</p>
<pre><code class="language-markdown hljs markdown" data-lang="markdown">| Name | Status | URL |
| ---- | ------ | --- |
| Matthew | online | mwop.net |
| An Example | offline | example.com |
| API | online | api.example.com |
</code></pre>
<p>This demonstrates the problem even better, as you can see that the columns do not align, which makes understanding if each row has all the required columns harder.</p>
<h3>Tabular</h3>
<p>The tabular plugin allows you to easily <em>tabularize</em> text.
You visually select the rows you want to line up, and then invoke it, providing a <em>search</em> string (a regular expression) for matching the character(s) to align against.
It then does the work of determining how much space to add to each column to get things to line up.</p>
<p>Going back to the original example, I'd select all the entries within the array, and then:</p>
<ul>
<li><code>:</code> to enter command mode</li>
<li><code>Tabularize /=&gt;</code> to invoke tabular, and tell it to align against <code>=&gt;</code></li>
<li><code>Enter</code></li>
</ul>
<p>and then you get:</p>
<pre><code class="language-php hljs php" data-lang="php">[
    <span class="hljs-string">"name"</span>   =&gt; <span class="hljs-string">"Matthew"</span>,
    <span class="hljs-string">"status"</span> =&gt; <span class="hljs-string">"online"</span>,
    <span class="hljs-string">"url"</span>    =&gt; <span class="hljs-string">"https://mwop.net"</span>
]
</code></pre>
<p>In the second example, I'd select all rows, including the header, and use <code>|</code> as the search.
This results in:</p>
<pre><code class="language-markdown hljs markdown" data-lang="markdown">| Name       | Status  | URL             |
| ----       | ------  | ---             |
| Matthew    | online  | mwop.net        |
| An Example | offline | example.com     |
| API        | online  | api.example.com |
</code></pre>
<blockquote>
<h4>Hint: use your tab key</h4>
<p>The Tab key is your friend, both in vim's command mode, as well as in your shell.
I generally type <code>:Tabu[Tab]</code>, and it expands to <code>:Tabularize</code> for me.
And, of course, you could bind it to a keystroke or function if you wanted.</p>
</blockquote>
<h3>However...</h3>
<p>Interestingly, I use tabular less and less.</p>
<p>Why?</p>
<p>My coding standard tools can do code alignment, and since I have to run this anyways, I can save myself some time by just <em>not</em> doing alignment during my coding session.</p>
<p>With markdown tables, my current markdown plugins and language server configuration autoindents for me.
As I finish a row, it automatically reformats the table to tabularize everything, which means I don't need to take any extra steps to format.</p>
<h3>Final Thoughts</h3>
<p>I keep this plugin around because when I <em>do</em> need it, it's super convenient, less error-prone than doing it manually, and saves me time.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2023-12-16-advent-vim-tabular.html">Advent 2023: (n)vim Plugins: tabular</a> was originally
    published <time class="dt-published" datetime="2023-12-16T14:56:00-06:00">16 December 2023</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Advent 2023: (n)vim Plugins: vim-surround</title>
      <pubDate>Fri, 15 Dec 2023 17:43:00 -0600</pubDate>
      <link>https://mwop.net/blog/2023-12-15-advent-vim-surround.html</link>
      <guid>https://mwop.net/blog/2023-12-15-advent-vim-surround.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>I've <a href="https://mwop.net/blog/tag/vim">blogged about vim a number of times</a>.
I've been using vim or its descendents for 22 years now; I switched to <a href="https://neovim.io">neovim</a> a few years back, but it's compatible with the existing vim ecosystem.
(The primary differences, to my mind, are that it has a more optimized engine which is more performant, and that you can now configure and extend it using <a href="https://www.lua.org">Lua</a> if you want.
Otherwise... it's just vim.)</p>
<p>I used to &quot;collect&quot; plugins, but at this point, particularly since switching over to neovim, I've reduced my plugins quite a bit, to only those I use on a regular basis.</p>
<p>So, I figured today, I'd start a mini-series as part of my Advent 2023 blogging, on some of my most used plugins.</p>
<p>Today's plugin: <a href="https://github.com/tpope/vim-surround">vim-surround</a>.</p>


<h3>What does it do?</h3>
<p>vim-surround, at it's heart, allows you to surround a selection with a character or pair of characters.</p>
<p>Why is this useful?</p>
<p>Let's say you're writing an exception message, and suddenly realize that you forgot to put it in quotes as you close the parens:</p>
<pre><code class="language-php hljs php" data-lang="php"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(This is the <span class="hljs-keyword">exception</span> message I will present)
</code></pre>
<p>Normally, I might use <code>f(</code> to jump to the first paren, hit <code>a</code> to append at that point, and then hit <code>'</code> to add the initial quote, and Esc to return to normal mode.
I'd repeat, but use <code>t)</code> to jump to the character before the closing paren.</p>
<p>With vim-surround, I can leverage vim's selection strokes to quickly do this.</p>
<ul>
<li>Hit <code>vi(</code> from anywhere within the parentheses, which selects everything between then.
I can even do this when on the &quot;)&quot; character; it performs the same selection.</li>
<li>Hit Shift-s to trigger vim-surround</li>
<li>Type <code>'</code> to surround the selected text with the quotes.</li>
</ul>
<p>This may not seem like much, but the amount of effort it saves is tremendous:</p>
<ul>
<li>I use it a ton when writing Markdown, to mark words or phrases as italic (<code>_</code>), bold <code>**</code> (this one requires doing the selection twice), or just to add quotes.</li>
<li>In HTML, I can use it to add tags!
When you trigger vim-surround, you can start typing a tag — e.g. <code>&lt;em&gt;</code> — and vim-surround will wait until the tag is complete, and then surround the selection with that tag.</li>
<li>In code, I'll often use it to surround a selection with parens or square brackets, or add quotes (as demonstrated above).</li>
</ul>
<h3>Sidebar: efficient selection</h3>
<p>Vim provides actions that give you the ability to select (<code>v</code>), replace (<code>c</code>), delete (<code>d</code>), and yank (<code>y</code>) text.
These actions operate on the selection you provide.</p>
<p>The selection <code>w</code> indicates to operate on the current <em>word</em>, and by default, it operates from the current position to the next <em>word boundary</em>.
This is important: the selection is really a <em>boundary</em> you wish to select <em>to</em>.</p>
<p>There are modifiers you can provide for the selection: &quot;i&quot; means &quot;inner&quot;, and will select everything <em>up to</em> the boundary, but not the boundary itself, but, more importantly, the boundary <em>to either side of the current position</em>.t</p>
<p>There are some boundaries that are particularly interesting: &quot;(&quot; and &quot;)&quot;, &quot;{&quot; and &quot;}&quot;, &quot;[&quot; and &quot;]&quot;, &quot;&lt;&quot;/&quot;&gt;&quot;, and both quote styles, when paired with &quot;i&quot; or &quot;a&quot; modifiers, will select <em>bewteen pairs</em>.</p>
<p>In the example above, I used <code>vi(</code> to select everything <em>inside</em> the parens.
&quot;a&quot; means &quot;all&quot;, and acts like &quot;i&quot;, but selects everything up to and including the boundary.
If I'd used <code>vaw</code> in the example, it would have selected everything inside the parens, <em>as well as</em> the parens.</p>
<p>You can be really efficient in your text selection and manipulation knowing these rules, and it's when using these rules that vim-surround shines.</p>
<h3>Final Thoughts</h3>
<p>It's the simplicity of operations such as text selection and using vim-surround that are a key reason for sticking with vim all these years.
They allow me to efficiently edit text without needing to leave the home row of the keyboard, or requriing a mouse.</p>
<p>So far in my career, I've avoided RSI, and I credit tools like this as a big part of that.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2023-12-15-advent-vim-surround.html">Advent 2023: (n)vim Plugins: vim-surround</a> was originally
    published <time class="dt-published" datetime="2023-12-15T17:43:00-06:00">15 December 2023</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Advent 2023: Logseq</title>
      <pubDate>Sat, 02 Dec 2023 23:59:59 -0600</pubDate>
      <link>https://mwop.net/blog/2023-12-01-advent-logseq.html</link>
      <guid>https://mwop.net/blog/2023-12-01-advent-logseq.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>In years past, folks across a variety of programming languages have organized Advent events in December, to highlight different tools, different frameworks, different programming practices, and more, often inviting guests to author each post.</p>
<p>I thought I'd try an experiment: I've had a ton of ideas for blog posts, many of them short, and just... never write them.
What if I were to do a personal advent, and write these up?</p>
<p>Let's see how far I get.</p>
<p>Today's topic: <a href="https://logseq.com">Logseq</a>.</p>


<h3>What was I trying to solve?</h3>
<p>For many years (over a decade), I kept a little knowledge base of markdown files.
I had a <code>diary</code> command that would open a file named after the current day's date, creating it if it didn't exist, in <a href="https://www.vim.org">vim</a>.
I'd create todo lists, notes from meetings, ideas I wanted to investigate, even blog and email drafts.</p>
<p>When I needed to find something, I'd use a tool such as <a href="https://beyondgrep.com">ack</a> to search through all files.</p>
<p>It worked, but I noticed a lot of things:</p>
<ul>
<li>For a long time, I'd have a TODO list for the day, and if I didn't finish items, I'd copy them to the next day's file.
This was tedious, though at one point I created a script to make it easier.
But worse: I discovered that the list would grow and grow, and lead to anxiety when I didn't finish them.
(Occasionally, I'd toss items off the list, in recognition that I'd likely never do them.)</li>
<li>Searching worked, but it was error prone.
I'd often forget to make search case insensitive.
Or the terms would return too many items.
Because it was regular expression based searching, there was no way to say &quot;find all files with this search term that also contain this other search term, but not necessarily in any proximity to each other.&quot;</li>
<li>It was great while I was on a computer, but next to impossible to use on a mobile or tablet.
As such, I tended to use it for work or for organizing programming projects, but not for the day-to-day.
And there's a lot I want to be able to come back to, much of it when I'm not at my computer: recipes, lists of things to watch and read, art inspiration, shopping lists, and more.
So having a file-based solution was not going to work.</li>
</ul>
<p>I tried a few different things over time:</p>
<ul>
<li>Evernote.
I actually used this for a couple of years, mainly to capture bookmarks, but cancelled it quite some time back (likely around 2017) when I realized I was getting locked into an ecosystem, and one that was increasingly moving away from how I actually wanted to use it.
And the fact that it didn't really allow linking between notes, or have a vim mode made it something I wouldn't open regularly.</li>
<li>Google Keep.
This was installed by default on my Android phone, and the data went with me... but it was difficult to use it on the computer, and the search for it was really spotty, which was surprising for a company that started as a search engine.</li>
<li><a href="https://github.com/nextcloud/notes">Nextcloud Notes</a>.
When I started using this, I imported my markdown files... and my instance was too underpowered to handle the sheer volume of notes I had.
On top of that, once I got the notes imported to Nextcloud, the Android app would choke trying to sync, and was super slow when I would try to use it.
And search... was not great.</li>
<li><a href="https://joplinapp.org">Joplin</a>.
This is an open source app that works on top of either Nextcloud Notes, or just on a filesystem.
Again, I struggled with the sheer number of notes I had, and the fact that I couldn't use it on mobile made it not a great fit for me.</li>
<li><a href="https://xwmx.github.io/nb/">nb</a>.
Somebody on Mastodon recommended this a little over a year ago, and I dove in as it was just markdown, vim, and the CLI. While it's text centric, it also has things like search and todo lists and more... but this was also it's hugest limitation: I couldn't feasibly use it on my phone or from my tablet.
On top of that, the way that lists worked, and the fact that if you wanted project-specific lists you essentially had to have separate collections, meant that I stuggled to use it regularly or stick with it.</li>
</ul>
<p>I've basically limped along, hopping from one solution to the next, without fully settling on any due to limitations.</p>
<h3>What is Logseq?</h3>
<p>Logseq is a <a href="https://en.wikipedia.org/wiki/Personal_knowledge_management">Personal Knowledge Manager</a> (PKM) application.
PKM tools provide a way to collect information, and, more importantly, surface it.
There's been a proliferation of these tools in the past years; you may have heard of <a href="https://obsidian.md">Obsidian</a>, <a href="https://www.notion.so">Notion</a>, and <a href="https://simplenote.com">SimpleNote</a>.
But the idea is not new; things like <a href="https://orgmode.org">Org Mode for emacs</a> have existed for ages, and some PKM ideas derive from the <a href="https://zettelkasten.de/introduction/">Zettelkasten method</a>.</p>
<p>Logseq itself is an open source application, built using Node and running in Electron; as such, it's cross-platform (I've used it on Linux, Android, iOS, and Windows).
It stores the actual content as <a href="https://www.markdownguide.org">Markdown</a>, though it uses tabs instead of spaces for indentation, and every line is a bullet point (more on this later).
Because it uses local file storage, you can use <a href="https://git-scm.org">git</a> to version files and sync between systems, or you can use any file syncing you have available.
(I've used <a href="https://syncthing.net">Syncthing</a>, <a href="https://nextcloud.com">Nextcloud</a>, and even OneDrive at work.)
The project rolled out a beta of a sync-as-a-service offering this past year, but I appreciate that it's not necessary or required in the least in order to use it.</p>
<h3>How does Logseq work?</h3>
<p>I started using this in late December or January of this past year, and was quickly surprised by what it enabled.</p>
<p>Let me explain.</p>
<p>When you open Logseq, you start in the <strong>Journal</strong>. This is a daily record, and once the day rolls over, it starts a new one.
99% of my work is done in the journal, and this is <em>fantastic</em>.
It allows me to understand <em>when</em> I learned something, had a meeting, or recorded a task.
While you <em>can</em> create separate pages, most of the stuff I want to track is relatively ephemeral.</p>
<p>Next, you can <strong>tag</strong> pages.
Let's say I'm writing a note, and it's related to PHP; I can type <code>#php</code>, and this becomes a link.
If I click that link, it takes me to the page — which may or may not exist.
But even if it does <em>not</em> exist, it will reference all the pages that link to it.
This is a cheap and easy way to organize things, and if I later want to add notes specific to that page, I can; it then becomes a first-class page in the system.</p>
<p>Tags are done as <strong>metadata</strong>, and metadata can be applied at the page level or item level.
Some, like <code>tags:: {tag list}</code> and <code>due:: {date}</code> are special to the system, and will surface functionality.
But they can be anything.
I've used them to be able to note page or item <em>types</em>, people I have meetings with (which I link to the pages for each person), and more.</p>
<p>You can also create <strong>templates</strong>.
These are text snippets that you want to re-use.
As examples, for work, I created templates for meetings (to allow me to indicate who the meeting was with,
when it happened, the agenda, any notes I took, and any action items from it), and for weekly prioritization (more on that later).
At home, I created templates for bookmarks (so I could give information on <em>why</em> I found the bookmark useful, the title of the page, and related tags), and recipes (so I could tag the type of food, specific ingredients, etc.).</p>
<p>Tagging pages makes it easy to <strong>search</strong>.
I can search, and if there's a page matching the keyword, I can go to it and immediately see what other notes I've taken on that subject.
Even better, though, Logseq includes both some basic search functionality that allows selecting for things like tags/pages, attributes (such as whether or not something is a task), and free text, and this can be done <em>within the page itself</em>, allowing you to see what matches immediately.</p>
<p>You can also create <strong>slash functions</strong> that pull in templates or evaluate to text.
An example I use frequently is one I installed from the Logseq marketplace, which creates a search for tasks completed in the past week.</p>
<p>All of this brings me to another cool feature.
I noted in the description of Logseq that each line in a page is a bullet point.
Logseq creates hashes for each of these, which allows referencing them.</p>
<p>This means you can:</p>
<ul>
<li>Link to any page or <em>item in a page</em>.</li>
<li>Embed items <em>anywhere</em>.
To do this, you right click on the bullet for the item, which allows you to copy a block embed; you then paste this in another page, and you see the content <em>right there</em>, and can even manipulate it from there!</li>
</ul>
<p>Because of all this functionality, Logseq <em>surfaces relevant information when you need it</em>.</p>
<p>Did you <em>schedule</em> something in the future?
If so, the Journal will show you upcoming scheduled items — not all of them, but the ones coming up <em>soon</em> (which you can define in the configuration).
You can create Journal pages for dates <em>in the future</em>, and if they include todo items... those will show up on the Journal as well, so you can remember.
I often create Journal pages ahead of time to create agendas for my one-on-ones; this ensures that those fleeting thoughts of &quot;I should ask them about so-and-so&quot; don't get forgotten when the day of the meeting rolls around.</p>
<h3>How do I use Logseq?</h3>
<h4>Prioritization</h4>
<p>My prioritization template for work brings in two search queries, one for pages with a <em>project</em> type that are <em>incomplete</em>, another for <em>incomplete tasks</em> that are not part of a project, which represents my backlog.
This allows me to go through each week and identify what on the backlog I can and/or should work on in the coming week, cancel tasks I recognize I will no longer do or which are no longer relevant, mark things as done that I may have completed this past week without realizing a task existed, and so on.</p>
<p>What I do is go through these items, and choose what I want to work on.
I then <em>embed</em> those items into the page for that week, which gives me a list <em>without duplication</em>, and which I can then reference later when I'm wanting to understand what I did that week.
I often also <em>schedule</em> items at that time, to ensure they surface on my journal pages.</p>
<p>At the end of the week, I run the query to show what I completed the past week on that prioritization page.
This gives me an excellent reference of what I <em>actually</em> did — which is often far more than I'd planned on for the week!
Often, if I find I did not finish what I set out to do that week, I can tell at a glance <em>why</em>: an unexpected request from my GM, a request from marketing, additional customer calls, etc.</p>
<p>These features have allowed me to be more intentional in my interactions with co-workers, ensure I'm more accountable to myself and to others in ensuring I get work done, and allow me to be better organized.</p>
<h4>Home cookbook</h4>
<p>I've tried a number of solutions for recipes in the past, including building my own apps.</p>
<p>The problem is (a) maintaining those apps, and (b) being able to find recipes when I need them.</p>
<p>For my personal Logseq instance, I created a template for recipes so that they are in a common structure, and that template includes metadata and tags so I can (a) find the original source if I need it, and (b) search for recipes by ingredients I commonly might have on hand.</p>
<p>I've got everything in it from recipes and tips for salting, brining, and seasoning, to main dishes, to cocktails.</p>
<p>Want to do a Rum-based cocktail?
Search for <code>(and [[rum]] [[cocktail]])</code>.
Need the instructions for brining and roasting the annual turkey?
Search for &quot;turkey&quot;.</p>
<p>It's been magical.</p>
<h4>Weekend projects and household todos</h4>
<p>I often know that I need to do something around the house, but forget by the time the weekend arrives.
I now create these as tasks in Logseq, with the tag &quot;weekend&quot;.
I can surface them quickly, and even use the ability to embed links to items to create a todo list for the weekend!</p>
<h3>Final words</h3>
<p>Would I recommend Logseq?</p>
<p>Wholeheartedly!</p>
<p>Look, it's not perfect.
The Markdown it uses is tab-delimited, and each line is a bullet point, which makes using it to draft blog posts or other Markdown a bit of a pain.
(I'm planning to write a tool to convert to standard Markdown over my holiday break, though!)
But it <em>is</em> Markdown, and it even supports things like blockquotes and fenced code blocks and tables, which gives a wealth of ways to format text.</p>
<p>On top of that, it has a rich plugin architecture and ecosystem.
You can do whiteboards, embed drawing widgets (I created an architectural diagram I shared with my engineering team using one of these!), create Kanban boards, or even use it as a full-featured calendar.
One I use extensively is a plugin giving Vim bindings, which allows me to move around and edit in ways that are relatively familiar.
If I absolutely have to, I can edit the files by hand (though with the slight differences in Markdown, this can sometimes introduce issues).</p>
<p>The fact that it is open source also means I can use it in perpeituity, so long as I am able to compile it and/or find an Electron version it works with.
And because it's using plain text and SQLite under the hood, I can take the data and use it however I want.</p>
<p>Is it the right tool for <em>you</em>?
I don't know.
I think the important thing is to try one of these tools and <em>stick with it</em>.
More and more functionality and content surfaces for me the longer I use the tool, and this is true of any good tool, I've found.
(I'm still learning things in vim to this day, and it's been 23 years of use to me!)</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/2023-12-01-advent-logseq.html">Advent 2023: Logseq</a> was originally
    published <time class="dt-published" datetime="2023-12-01T23:59:59-06:00">1 December 2023</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Vim Toolbox, 2010 Edition</title>
      <pubDate>Fri, 17 Dec 2010 03:50:53 -0600</pubDate>
      <link>https://mwop.net/blog/249-vim-toolbox-2010-edition.html</link>
      <guid>https://mwop.net/blog/249-vim-toolbox-2010-edition.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>I've been using <a href="http://www.vim.org/">Vim</a> for close to a decade. I've often
said that <em>&quot;Unix is my IDE&quot;</em> — because Vim is built in the Unix philosophy,
allowing me to pipe input into it, out of it, and every which way I want. It
fits very nicely with the Unix philosophy of doing one task well, and allowing
redirection. I've found it ideal for web development in general and PHP
development specifically — in fact, I've had excellent experiences in every
language I've tried my hand at developing in when using Vim.</p>
<p>Vim is also my chosen productivity suite. When I want to write a document, I
don't go into OO.o Writer or MS Word or some other word processor; I open up a
window and start typing. In most cases, I can either cut and paste my work into
other tools, or pipe it to transformation tools. I worry about the <em>content</em>
first, and the <em>presentation</em> later… like any good MVC application. ;-)</p>
<p>Like any good tool, you have to invest time in it in order to reap its benefits.
My learning has, to date, fallen into three time periods:</p>
<ul>
<li>The initial months in which I first learned Vim, via vimtutor and Steve
Oualline's Vim book.</li>
<li>A period in 2006-2007 when I felt the need to make my coding more efficient,
and first started playing with exuberant-ctags and omni-completion.</li>
<li>The last quarter of 2010 (yes, that's now) when I was introduced to a number
of new tools via Twitter.</li>
</ul>
<p>So, this is my Vim Toolbox, 2010 edition.</p>


<h2>Getting Plugins</h2>
<p>I've added two primary ways to add new plugins to my arsenal:</p>
<ul>
<li>
<p><a href="https://github.com/c9s/Vimana">Vimana</a>, which is a command-line tool for
discovering, downloading, installing, and upgrading scripts found on
<a href="http://www.vim.org">vim.org</a>. It's not perfect, but if you know the name of
the script, and it's provided in either a
<a href="http://www.vim.org/scripts/script.php?script_id=1502">vimball</a> format and/or
follows the Vim runtime file structure, it's a great way to keep your plugins,
syntax files, etc. up-to-date.</p>
</li>
<li>
<p><a href="http://tammersaleh.com/posts/the-modern-vim-config-with-pathogen">Vim Pathogen</a>
allows you to install plugins as &quot;bundles&quot;, allowing you to keep them
up-to-date separately, in their own file tree. This looks like the following:</p>
<pre><code class="language-vim hljs vim" data-lang="vim">.<span class="hljs-keyword">vim</span>/
    bundle/
        <span class="hljs-keyword">vim</span>-task/
            ftdetect/
            ftplugin/
            <span class="hljs-keyword">syntax</span>/
</code></pre>
<p>In short, a &quot;bundle&quot; mimics the structure of a Vim directory.</p>
</li>
</ul>
<p>The latter, Pathogen, is my preferred installation method of choice at this
point. Why? One acronym: DVCS.</p>
<p>A ton of popular Vim plugins are now being either developed or mirrored on
GitHub or other DVCS sites. This allows you to clone them and then create a
branch that's specific to your configuration. As an example, the popular
<a href="http://www.vim.org/scripts/script.php?script_id=2540">snipMate plugin</a> has its
key-bindings hard-coded — which causes problems if you're already using those
bindings. Which, if you're using any form of omni-completion, is all too likely.
I simply <a href="https://github.com/weierophinney/snipmate.vim">cloned the snipMate repo</a>, and created a branch for
my configuration (I use <code>&lt;Leader&gt;&lt;tab&gt;</code> to invoke it).</p>
<p>Now, it gets even better: I've made <a href="http://git.mwop.net/?a=summary&amp;p=vimrc">a git repository for my Vim configuration</a>;
with judicious use of <code>git submodule</code>, I can now add pathogen bundles as
submodules of my repository. Right now, I've got bundles for html5.vim,
mustache.vim, NErdtree, snipMate, TagList, vim-fugitive, vim-task, and vimwiki.
This keeps my repository lean, while retaining the features I need and use
daily.</p>
<p>As part of creating my Vim configuration repository, I also made a few changes
to facilitate the process. First, I moved <code>$HOME/.vimrc</code> to <code>$HOME/.vim/vimrc</code>,
and symlinked the former to the latter. This allows me to keep all my Vim
configuration in one place.</p>
<p>Next, I moved my Vim view files outside the directory; this data is volatile and
constantly changing, and really does not need to be versioned. These are now in
my <code>$HOME/.vim.view/</code> directory. Finally, I moved my tag files into a new
<code>$HOME/.vim.tags/</code> directory. More on that later, but, again, the rationale is
that this data is volatile and does not need to be versioned.</p>
<h2>DVCS</h2>
<p>I mentioned I created a Git repository for my Vim configuration. In part, this
is due to the fact that I'm proficient with Git — I use it day-in, day-out. Hg
and other DVCS systems are also great; I'm not using them nearly as often,
however.</p>
<p>To that end, I'm now using
<a href="https://github.com/tpope/vim-fugitive">vim-fugitive</a>. The author boasts that
it's &quot;a Git wrapper so awesome, it should be illegal&quot;; I wouldn't necessarily go
that far, but I do find it incredibly useful. While I'm typically working in a
console, I also find myself in GVim windows regularly as well — and having a
nice, familiar interface to Git is very useful. If you use both Vim and Git, I
highly recommend checking out vim-fugitive.</p>
<h2>Filesystem Navigation and Projects</h2>
<p>At some point, unless you're one of those developers who likes to code
everything in a single file, you need to do some sort of navigation. A couple
years back, <a href="http://zmievski.org/">Andrei Zmievski</a> introduced me to
<a href="http://www.vim.org/scripts/script.php?script_id=1658">NErdtree</a>, a dead-simple,
colorized navigation. I use this every. single. day.</p>
<p>I also use a tool called
<a href="http://www.vim.org/scripts/script.php?script_id=69">Project</a>. This tool allows
you to specify &quot;files of interest&quot; to a project — either by automatically
scanning a tree, or manually. Additionally, the way you specify the hierarchy
can be entirely arbitrary — allowing you to flatten the tree when it's getting
in the way. I use this tool regularly as well, though not quite as much as
NErdtree.</p>
<h2>Navigating Code</h2>
<p>One often touted feature of modern IDEs is code completion and hinting. These
are definitely useful features, particularly when working on unfamiliar code, or
code you haven't touched in some time.</p>
<p>Vim actually has some great tools for this already. One is built-in:
omni-completion (<code>:he new-omni-completion</code> for Vim's help on the feature). By
default, it inspects the files in open buffers to provide completion (assuming
it has a definition for that language and/or syntax highlighting) — but it can
also utilize <em>tag</em> files.</p>
<p>The built-in omni-completion for PHP is reasonable — you can jump around by
class names, function/method names, variables, etc. It gets much, much more
useful, however, when you utilize tag files, as you don't need the files already
open in order to get completion. I've <a href="/blog/134-exuberant-ctags-with-PHP-in-Vim.html">blogged about ctags before</a>;
however, I've updated my scripts a bit.</p>
<p>First, exuberant-ctags is much more PHP aware now than when I blogged. This
means you don't need to do any special regex-fu in order to properly identify
abstract classes, interfaces, and methods. Second, I found that I could generate
a single script with prompts to indicate the directory and tag file name.
<a href="http://git.mwop.net/?a=viewblob&amp;p=vimrc&amp;h=3a8ca75bcd6a28dbea2cee02f31d72e82f415e5b&amp;hb=c1a728c96fa593be5c570c78cac5dcb2b7052fd3&amp;f=bin/mkTags">That script</a>
basically looks like this:</p>
<pre><code class="language-bash hljs bash" data-lang="bash"><span class="hljs-meta">#!/bin/sh</span>
dir=<span class="hljs-string">""</span>
name=<span class="hljs-string">""</span>
<span class="hljs-keyword">if</span> [ <span class="hljs-variable">$#</span> -ge 2 ] ; <span class="hljs-keyword">then</span>
    <span class="hljs-comment"># Two arguments: first is directory, second is "alias"</span>
    dir=<span class="hljs-variable">$1</span>
    name=<span class="hljs-variable">$2</span>
<span class="hljs-keyword">else</span>
    <span class="hljs-keyword">if</span> [ <span class="hljs-variable">$#</span> -eq 1 ] ; <span class="hljs-keyword">then</span>
        <span class="hljs-comment"># One argument: use as directory, and use basename of directory as alias</span>
        dir=<span class="hljs-variable">$1</span>
        name=`basename <span class="hljs-variable">$1</span>`
    <span class="hljs-keyword">else</span>
        <span class="hljs-comment"># Otherwise: prompt</span>
        <span class="hljs-built_in">echo</span> <span class="hljs-string">"Enter the path to a directory containing PHP code you wish"</span>
        <span class="hljs-built_in">echo</span> <span class="hljs-string">"to create tags for:"</span>
        <span class="hljs-built_in">read</span> dir
        <span class="hljs-built_in">echo</span> <span class="hljs-string">"Enter the name of the tagfile you wish to create:"</span>
        <span class="hljs-built_in">read</span> name
    <span class="hljs-keyword">fi</span>
<span class="hljs-keyword">fi</span>

<span class="hljs-built_in">echo</span> <span class="hljs-string">"Creating tags for directory '<span class="hljs-variable">$dir</span>' using alias '<span class="hljs-variable">$name</span>'"</span>
<span class="hljs-built_in">cd</span> <span class="hljs-variable">$dir</span>
<span class="hljs-built_in">exec</span> ctags-exuberant -f ~/.vim.tags/<span class="hljs-variable">$name</span> \
-h <span class="hljs-string">".php"</span> -R \
--exclude=<span class="hljs-string">"\.svn"</span> \
--totals=yes \
--tag-relative=yes \
--fields=+afkst \
--PHP-kinds=+cf 
<span class="hljs-built_in">echo</span> <span class="hljs-string">"[DONE]"</span>
</code></pre>
<p>Two things to note:</p>
<ul>
<li>It creates the tag files in <code>$HOME/.vim.tags/</code>. I do this as my tag files
change fairly regularly, and can be re-generated on the fly as needed. There's
no reason to version them.</li>
<li>Once generated, you need to load them. I created a &quot;LoadTags&quot; Vim function
that will load a tag file by the given name from the <code>$HOME/.vim.tags/</code>
directory. By default, I load the ones I most commonly use (ZF1, ZF2,
PHPUnit). Otherwise, a quick <code>:Ltag &lt;tag filename&gt;</code> will load on-demand.</li>
</ul>
<p>Once the tags are created, you can use Vim's normal tag features to load files,
jump to files, etc. The most common commands I use are:</p>
<ul>
<li><code>:stag &lt;tagname&gt;</code>, which splits the current window and loads the given tag in the newly created split.</li>
<li><code>&lt;Ctrl-w&gt;]</code>, when on text you suspect of being a tag (such as a classname),
will split the current window and load that tag file in the new pane.</li>
</ul>
<p>These two commands I use constantly, and are huge timesavers — I can basically
use the code as my documentation.</p>
<p>Additionally, the main use of omni-completion is to give tab-completion for
known tags. This means that you can start typing, hit <code>&lt;Tab&gt;</code>, and either have
it immediately complete, or give you a list of potential matches. It's not quite
as useful as a good IDE — it's not context-aware, so you'll get <strong>any</strong>
potential match from <strong>any</strong> class — but it's better than nothing, provides
reasonable hinting, and helps protect you from spelling errors.</p>
<p>That said, there's also something to be said about just having the signatures
and prototypes of the various methods easily accessible. For that, there's the
<a href="http://vim-taglist.sourceforge.net/">Vim TagList</a> plugin. This plugin will scan
open files and produce a list of classes, variables, and methods. With this
list, you can get the method prototypes, as well as jump directly to their
definitions. Pressing <code>&lt;Space&gt;</code> will show you the prototype, <code>&lt;CR&gt;</code> will jump to
it.</p>
<p>Between these two features (omni-completion with tags and TagList), I have most
of the useful features of any IDE immediately available.</p>
<h2>Working With Code</h2>
<p>Since I sling code for a living, it's useful to have some plugins and syntax
highlighting to make working with code easier.</p>
<p>First off, I've been experimenting with HTML5; as such, I added the
<a href="https://github.com/othree/html5.vim">html5.vim</a> syntax highlighting as a
Pathogen module. This adds support for a bunch of HTML5-specific features, while
retaining the fantastic HTML support already in the official HTML syntax
provided with Vim.</p>
<p>Next, I use the <a href="http://www.vim.org/scripts/script.php?script_id=967">php.vim</a>
syntax file from vim.org. This particular syntax file has support for PHP 5.3
features, which come in very handy while I'm coding for ZF2. The author of this
syntax has also created a script (<code>php_vimgen.php</code>) for generating syntax files
for core classes as well as extensions using the Reflection API. I've modified
the tool in my repository to strip out the generated syntax, and instead source
it from the file created with the <code>php_vimgen.php</code> script; I've also altered
said script to create the syntax in <code>__DIR__ . '/php_syntax_vimgen.vim'</code>,
ensuring I can always source it from the same location. This allows me to keep
my PHP syntax highlighting up-to-date.</p>
<p>Finally, I use <a href="http://www.vim.org/scripts/script.php?script_id=2540">snipMate</a>,
a tool that emulates TextMate's &quot;snippet&quot; features. Basically, this is
dead-simple, templated code generation. You can write your own files
(<a href="http://git.mwop.net/?a=tree&amp;p=vimrc&amp;h=5990c978d877f9dcad2a02239ae3af74bcb75ba4&amp;hb=c1a728c96fa593be5c570c78cac5dcb2b7052fd3&amp;f=snippets/php">I did</a>),
or use those that come with it. Once you've got some snippets, you type a word
(usually a mnemonic for the operation you're trying to perform), and it will
either just spit up a template, or optionally provide &quot;prompts&quot; for you to fill
in (along with variable completion!). Basically, I never code accessors and
mutators anymore; snipMate does these for me, with a little prompting.</p>
<h2>Organization</h2>
<p>I use Vim day-in, day-out, for all sorts of things: mail, drafting blog posts,
drafting presentation outlines, taking meeting notes, managing my todo list, and
more. As such, I try to keep as much of my &quot;organization&quot; within Vim — it's just
easier.</p>
<p>I've tried a number of tools over the years. For a good 4 or 5 years, my primary
tool was <a href="http://www.vimoutliner.org/">VimOutliner</a>. It provided decent syntax,
decent folding, and reasonable HTML generation from the outline. However, in
recent years, I feel the project had stalled, and I also found that the way I
wanted to use it had changed: outlining is great, but I often want to use the
outline as a starting point for generating content; task tracking is fine, but I
found, for whatever reason, that the way VimOutliner handled task status often
didn't work well — either from a tooling or a syntax standpoint.</p>
<p>At some point, <a href="http://twitter.com/tswicegood">Travis Swicegood</a> introduced me
to <a href="http://code.google.com/p/vimwiki/">vimwiki</a>. This tool provides a personal
wiki <em>within</em> Vim. This tool allowed me to organize my notes in an ad-hoc,
semi-hierarchical way, link back and forth between them, and have not only
reasonable in-editor highlighting, but great HTML generation. This allowed me to
ditch VimOutliner for everything but task tracking. Once I made my &quot;wiki&quot;
directory a Git repository, I then received versioning basically for free
(especially with vim-fugitive, which makes it easy for me to hit <code>:Gwrite</code> and
<code>:Gcommit</code> when I create and/or update files).</p>
<p>Another feature vimwiki provides is a &quot;diary&quot;. You access it using
<code>&lt;Leader&gt;w&lt;Leader&gt;w</code>, which opens up a new wiki page for the current day (or, if
you already opened it before, re-opens the one created earlier in the day). This
is a really useful tool for taking notes during meetings, or when doing
research, etc.</p>
<p>Couple these features with integrated search (<code>:VWS /pattern/</code>), and vimwiki is
<em>the</em> killer productivity tool in my toolbox.</p>
<p>At another point, Travis then pointed out another tool:
<a href="https://github.com/samsonw/vim-task">vim-task</a>. This is perhaps the most
dead-simple task tracker I've ever used; each line is a task, and is either
incomplete (starts with a &quot;-&quot;), or complete (starts with a checkmark). A simple
keybinding, which I've mapped to <code>&lt;Leader&gt;m</code>, toggles status - and complete
items get highlighted in green and italicized, making you feel good and giving a
good visual queue as to what you've completed.</p>
<p>At some point, Travis also tossed out the idea that combining vimwiki with
vim-task would be useful — and I latched onto this idea. I've now created
<a href="https://github.com/weierophinney/vimwiki/tree/feature/vim-task">a fork of vimwiki with vim-task integration</a>,
which allows me to keep my tasks and notes in a single place… and, since my wiki
is versioned, my tasks are as well.</p>
<h2>Various Oddities</h2>
<p>As I mentioned at the start of this post, I've been using Vim for close to a
decade. Part of the reason Vim was appealing to me was due to the fact that it
kept me in the &quot;home row&quot; of the keyboard — which provides a huge amount of
efficency. You don't have to move to the arrow keys to scroll, no leaving the
keyboard for the mouse, etc. That said, some key combinations are difficult to
reach:</p>
<ul>
<li>The placement of the <code>&lt;Esc&gt;</code> key varies from keyboard to keyboard, and is
rarely in a place that is easy to reach. On my current keyboard, it's in the
top left corner, above the function keys; it's impossible to reach without
moving my hand. A tip I picked up pretty much when I began using Vim was to
map <code>jj</code> to <code>&lt;Esc&gt;</code>; it's rare to type a <code>j</code> repeatedly in the English
language, and it's dead-center on the home row. This is incredibly efficent.</li>
<li>I've mapped my Caps Lock key to <code>&lt;Ctrl&gt;</code> on every system I've owned in the
past decade. I never used it, and it's almst always on the home row. Again,
hugely efficient.</li>
<li>Keybindings are great, but there's so many already in use that it's hard <em>not</em>
to overwrite existing ones. Using the <code>&lt;Leader&gt;</code> key to define keybindings has
been great. As examples, I mapped <code>&lt;Leader&gt;m</code> to toggle tasks, and
<code>&lt;Leader&gt;&lt;Tab&gt;</code> to invoke snipMate.</li>
</ul>
<p>In Vim, <code>&lt;C-m&gt;</code> has long been the &quot;make&quot; binding, and <code>&lt;C-l&gt;</code> for linters. In
languages like PHP and JavaScript, these often don't make sense. However, I've
bound these in both languages — in PHP, &quot;make&quot; executes the current script using
the PHP executable, while &quot;lint&quot; runs it through the PHP linter. In JS, I leave
&quot;make&quot; unbound, while &quot;lint&quot; runs the script through jslint.</p>
<p>I've also added the &quot;php-doc.vim&quot; plugin, and mapped <code>&lt;C-P&gt;</code> to create PHP
docblocks; the plugin is context aware, and will create appropriate annotations.</p>
<h2>Cloning my repo</h2>
<p>As noted, I've created a repository for my Vim configuration. If you want to
clone it and explore it, you can do so as follows:</p>
<ul>
<li>Browse the repository: <a href="http://git.mwop.net/?a=summary&amp;p=vimrc">http://git.mwop.net/?a=summary&amp;p=vimrc</a></li>
<li>Clone the repo: <code>git clone git://mwop.net/vimrc.git</code></li>
</ul>
<p>Be aware that there a number of git submodules in play (all the pathogen modules
are git submodules). To initialize these, simply run <code>git submodule init</code>
followed by <code>git submodule update</code> after you clone the repository.</p>
<h2>Resources</h2>
<p>I didn't learn all this overnight. As with any toolset, it's only as good as the
amount of time you invest learning it. For me, my primary resources lately have
been:</p>
<ul>
<li><a href="http://twitter.com/#!/search/%23vim">#vim hashtag on Twitter</a></li>
<li><a href="http://vimcasts.org/">VimCasts</a> are a fantastic source of information, provided by Drew Neil. Seriously, these are <strong>completely</strong> worth the time spent watching them.</li>
<li><a href="http://twitter.com/tswicegood">Travis Swicegood</a> has tweeted a number of times about interesting things he does with Vim and Git, and inspired me to write the vim-task syntax for vimwiki.</li>
</ul>
<h2>More Tools</h2>
<p>This post has been on my <em>Vim</em> toolbox. I've also been usig a number of other
tools lately — <a href="http://tmux.sourceforge.net/">tmux</a>, <a href="http://www.zsh.org/">zsh</a>
(in particular, git prompts), <a href="http://hotot.org/">Hotot</a> (GTK2 + WebKit Twitter
client), and more; I may blog about those in the future — using Vim. ;-)</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/249-vim-toolbox-2010-edition.html">Vim Toolbox, 2010 Edition</a> was originally
    published <time class="dt-published" datetime="2010-12-15T07:49:00-06:00">15 December 2010</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Vimgrep and Vim Project</title>
      <pubDate>Wed, 22 Oct 2008 21:55:03 -0500</pubDate>
      <link>https://mwop.net/blog/194-Vimgrep-and-Vim-Project.html</link>
      <guid>https://mwop.net/blog/194-Vimgrep-and-Vim-Project.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>Chris Hartjes today was
<a href="http://www.littlehart.net/atthekeyboard/2008/10/20/vim-programming-bounty-fuzzyfind-inside-files/">on a quest for a &quot;find in project&quot; feature for Vim</a>.
&quot;Find in Project&quot; was a feature of Textmate that he'd grown accustomed to and
was having trouble finding an equivalent for.</p>
<p>The funny thing is that Textmate is a newcomer, and, of course, vim has had
such a feature for years. The thing to remember with vim, of course, is its
unix roots; typically if you know the unix command for doing something, you can
find what you need in vim. In this case, the key is the vimgrep plugin, which
ships in the standard vim distribution.</p>


<p>There are a variety of resources on vimgrep. The vim documentation includes a
chapter on it, and a quick <a href="http://www.google.com/search?q=vimgrep">google search</a>
on the subject turns up some nice tutorials immediately. If you've ever used
grep, the syntax is very straightforward:</p>
<pre><code class="language-markdown hljs markdown" data-lang="markdown">vimgrep /{pattern}/[<span class="hljs-string">g</span>][<span class="hljs-symbol">j</span>] {file} ...
</code></pre>
<p>The &quot;g&quot; option indicates that all matches for a search will be returned instead
of just one per line, and the &quot;j&quot; option tells vim <em>not</em> to jump to the first
match automatically. What does the &quot;g&quot; flag really mean, though, and how are
searches returned?</p>
<p>Vimgrep returns search results in what's known as a &quot;quickfix&quot; window, and this
is where the vimgrep documentation falls apart… it doesn't explain what this
is, or link to it (which would be a nice indication that it actually has a
separate topic for this).</p>
<p>The Quickfix window is a pane that shows a search result per line. Each line
shows the file that matches, the line number, and the contents of that line:</p>
<pre><code class="language-awk hljs awk" data-lang="awk"><span class="hljs-regexp">/home/m</span>atthew<span class="hljs-regexp">/git/</span>bugapp<span class="hljs-regexp">/application/</span>controllers<span class="hljs-regexp">/helpers/</span>GetForm.php|<span class="hljs-number">10</span>| * @var Zend_Loader_PluginLoader
</code></pre>
<p>You can't do much from this window; it simply serves as a visual indicator of
what file you're currently looking at from the list. However, in the main
window, you can start iterating through the results one at a time, using a
subset of the Quickfix commands. As a quick summary:</p>
<ul>
<li><strong>:cc</strong> will move to the next match in the list</li>
<li><strong>:cn</strong> will move to the next match in the list</li>
<li><strong>:cp</strong> will move to the previous match in the list</li>
<li><strong>:cr</strong> will rewind to the first match in the list</li>
<li><strong>:cla</strong> will fast forward to the last match in the list</li>
</ul>
<p>When done, you can simply close the Quickfix window/pane, and continue working.</p>
<p>I should note that vimgrep <em>is</em> cross-platform. On *nix-based systems, it
defaults to using the native grep command, but it also contains an internal
(slower) implementation for use on operating systems that do not provide grep
by default. You may also map the command to alternate implementations if
desired.</p>
<p>I personally use this feature most with the <a href="http://www.vim.org/scripts/script.php?script_id=69">project plugin</a>.
Project maps vimgrep to two different commands: <code>&lt;Leader&gt;g</code> and <code>&lt;Leader&gt;G</code>.
The first will grep all files in the current project at the current level; the
second does the same, but also recurses into subprojects. This is an incredibly
easy way to refactor code, particularly for name changes.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/194-Vimgrep-and-Vim-Project.html">Vimgrep and Vim Project</a> was originally
    published <time class="dt-published" datetime="2008-10-21T07:36:49-05:00">21 October 2008</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Vim Productivity Tips for PHP Developers</title>
      <pubDate>Tue, 25 Mar 2008 11:39:35 -0500</pubDate>
      <link>https://mwop.net/blog/164-Vim-Productivity-Tips-for-PHP-Developers.html</link>
      <guid>https://mwop.net/blog/164-Vim-Productivity-Tips-for-PHP-Developers.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>I use <a href="http://www.vim.org/">Vim</a> for all my editing needs — TODO lists, email,
presentation outlines, coding in any language… everything. So, I thought I'd
start sharing some of my vim habits and tools with others, particularly those
that pertain to using Vim with PHP.</p>


<h3>Mapping the PHP interpreter and linter to keystrokes</h3>
<p>Probably the most useful thing I've done as a PHP developer is to add mappings
to run the current file through (a) the PHP interpreter (using <code>Ctrl-M</code>), and (b)
the PHP interpreter's linter (using <code>Ctrl-L</code>). These are accomplished with the
following:</p>
<pre><code class="language-asciidoc hljs asciidoc" data-lang="asciidoc">" run file with PHP CLI (CTRL-M)
<span class="hljs-meta">:autocmd FileType php noremap &lt;C-M&gt; :w!&lt;CR&gt;:!$HOME/bin/php</span> %&lt;CR&gt;

" PHP parser check (CTRL-L)
<span class="hljs-meta">:autocmd FileType php noremap &lt;C-L&gt; :!$HOME/bin/php</span> -l %&lt;CR&gt;
</code></pre>
<p>(I have <code>\~/bin/php</code> as my PHP interpreter, which allows me to run PHP with a
custom config file, as well as to change which PHP binary I'm using.)</p>
<p>These two commands allow me to quickly and easily check that my syntax is okay,
as well as to run unit test suites easily.</p>
<h3>Vim Project</h3>
<p>Next up is the excellent <a href="http://www.vim.org/scripts/script.php?script_id=69">Project plugin</a>.</p>
<p>&quot;Project&quot;, at its most basic, allows you to setup a navigation pane with a list
of files related to your project. The files are typically organized by
directory, but the beauty is that the hierarchy can be defined however it makes
sense for your given project. It also has tools for creating projects based on
a given directory, recursively pulling in files based on filters you specify.
Type <code>:help project</code> to get documentation on this after you install it; <code>\C</code>
will help you create your first project.</p>
<p>Each project can consist of one or more project folds; these can be sub
projects, or a self-defined hierarchy or grouping of files. For instance, in my
Zend Framework project file, I have &quot;library&quot;, &quot;tests&quot;, and &quot;documentation&quot;
folds — &quot;library&quot; points to &quot;library/Zend/&quot;, &quot;tests&quot; points to &quot;tests/&quot;, and
&quot;documentation&quot; points to &quot;documentation/manual/en/&quot;. Within each, I then have
folds for each subdirectory. Since directories and subprojects are specified as
folds, you can use Vim's native folding mechanisms to keep only the file of
interest visible, which is very handy.</p>
<p><img src="/uploads/2008-03-22-VimProject.png" alt="Vim Project" /></p>
<p>Basically, Project allows vim to act like a minimal IDE. With the file list on
the left, you simply hit enter on a file, and it loads in the main pane. More
fun is when you use the <code>\S</code> command, which will split the main pane and load
the file into the new pane. This is particularly useful when doing Test Driven
Development, as you can have one pane for the unit test code, and another for
the class file, allowing you to jump back and forth between them. Add to this
the <code>Ctrl-M</code> and <code>Ctrl-L</code> commands I listed earlier, and you're now also able to
quickly and easily check your files for syntax errors and run tests directly
within the Vim window.</p>
<p><img src="/uploads/2008-03-22-VimUnitTests.png" alt="Vim Project" /></p>
<p>There are other commands, too. You can run all files through a particular
script, grep all files in a project, map particular file types to specific
launchers, etc. Combine it with other Vim functionality, and you have a
minimal, yet powerful, IDE at your disposal that launches in under a second.</p>
<p>By default, Project stores projects in <code>$HOME/.vimprojects</code>. I find that I don't
necessarily want all my projects at any given time, so I've created a
<code>$HOME/.projects/</code> directory that has a project entry for each project — I
simply save the contents of a project fold to files under this tree. I can then
perform <code>:r ~/.projects/&lt;projectname&gt;</code> to read in a given project when I want
to work on it. This helps me keep my workspace uncluttered, and also helps me
focus on a given project at a time.</p>
<h3>Ctags</h3>
<p>I've <a href="/blog/134-exuberant-ctags-with-PHP-in-Vim.html">covered ctags</a> elsewhere,
so I won't cover them here, but with ctags defined, I get tab completion for
most classes and methods (and Vim takes care of tab-completion for class
members in the current class file), as well as the ability to quickly and
easily open class files for classes I've tagged — which is useful when you want
to see what methods are available and how they work.</p>
<hr />
<p>I'll try and cover other vim techniques I use in upcoming blog entries. Those
listed in here, though, have greatly increased my productivity, and are things
I use daily.</p>


<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/164-Vim-Productivity-Tips-for-PHP-Developers.html">Vim Productivity Tips for PHP Developers</a> was originally
    published <time class="dt-published" datetime="2008-03-22T10:41:26-05:00">22 March 2008</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>exuberant ctags with PHP in Vim</title>
      <pubDate>Thu, 25 Mar 2010 16:18:59 -0500</pubDate>
      <link>https://mwop.net/blog/134-exuberant-ctags-with-PHP-in-Vim.html</link>
      <guid>https://mwop.net/blog/134-exuberant-ctags-with-PHP-in-Vim.html</guid>
      <author>contact@mwop.net (Matthew Weier O'Phinney)</author>
      <dc:creator>Matthew Weier O'Phinney</dc:creator>
      <content:encoded><![CDATA[<p>One reason I've heard PHP developers use for adopting an IDE when developing is
the ability to click on a class or function name and jump to the declaration.
Sounds like magic, and it's definitely something I've desired.</p>
<p>One way I get around it is by adopting PEAR coding standards for naming my
classes. Since they define a one-to-one mapping of class name to the file
system (substitute the underscore character (<code>_</code>) with the directory
separator), I can usually very quickly and easily open a class file,
particularly if I start in the base directory of the project install.</p>
<p>Today, however, I found <a href="http://ctags.sourceforge.net">exuberant ctags</a>, a
library which can be used to generate an index file mapping language objects to
source files and the line in the source file where they are declared. Contrary
to its name, it's not just for the C language; it currently supports 33
different programming languages, including PHP.</p>
<p>I decided to try it out on the Zend Framework core library today. At first run,
it was pretty useful. However, it was only mapping classes, and, in addition,
only those defined with the single word 'class' — abstract classes and
interfaces were entirely left out. So, I looked into the documentation to see
if I could change the behaviour.</p>
<p>And, being a Unix program, of course I could. First off, you can add functions
to the items it indexes with a simple flag. Additionally, you can use POSIX
regular expressions to refine what it searches.</p>
<p>I whipped up the following script to create my tags index:</p>
<pre><code class="language-bash hljs bash" data-lang="bash"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-built_in">cd</span> /path/to/framework/library
<span class="hljs-built_in">exec</span> ctags-exuberant -f ~/.vim/mytags/framework \
-h \".php\" -R \
--exclude=\"\.svn\" \
--totals=yes \
--tag-relative=yes \
--PHP-kinds=+cf \
--regex-PHP=<span class="hljs-string">'/abstract class ([^ ]*)//c/'</span> \
--regex-PHP=<span class="hljs-string">'/interface ([^ ]*)//c/'</span> \
--regex-PHP=<span class="hljs-string">'/(public |static |abstract |protected |private )+function ([^ (]*)//f/'</span>
</code></pre>
<p>This script creates the tag index in the file <code>$HOME/.vim/mytags/framework</code>. It
scans for PHP files recursively through the tree, excluding any files found in
a <code>.svn</code> directory (I'm using a checkout from the subversion repository). The
file paths in the index are created relative to the tags file; this was
important, because if this wasn't provided, vim was unable to jump to the file,
as it couldn't find it. <code>--PHP-kinds=+cf</code> tells it to index classes and
functions. Next, I've got three regular expressions. The first tells it to
match classes beginning with 'abstract class' as classes. The second tells it
to match interfaces as classes. The last is so that PHP 5 methods, which begin
with a visibility operator, to be matched as functions.</p>
<p>Once the index file is generated (it takes less than a second), all you need to
do in vim is tell it to load it: <code>:set tags=~/.vim/mytags/framework</code>. At this
point, you can do all sorts of fun stuff. Place the cursor on a class name or
method name, anywhere in it, and hit <code>Ctrl-]</code>, and you'll jump to the file and
line of its declaration; <code>Ctrl-T</code> then takes you back. If you change the
invocation to <code>Ctrl-W ]</code>, it will split the current window and open the
declaration in the new pane. (If you're familiar with how help works with Vim,
this should seem pretty familiar.)</p>
<p>One more reason to stick with Vim for your PHP editing needs. :-)</p>




<div class="h-entry">
    <img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&u=79dd2ea1d4d8855944715d09ee4c86215027fa80&s=140" alt="matthew">
    <a class="u-url u-uid p-name" href="https://mwop.net/blog/134-exuberant-ctags-with-PHP-in-Vim.html">exuberant ctags with PHP in Vim</a> was originally
    published <time class="dt-published" datetime="2007-01-31T14:20:00-06:00">31 January 2007</time>
    on <a href="https://mwop.net">https://mwop.net</a> by
    <a rel="author" class="p-author" href="https://mwop.net">Matthew Weier O&#039;Phinney</a>.
</div>
]]></content:encoded>
      <slash:comments>0</slash:comments>
    </item>
  </channel>
</rss>
