<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Jeff Bailey | Learn X - Development - Command Line</title><link>https://jeffbailey.us/categories/learn-x---development---command-line/</link><description>This website contains learning resources, opinions, and facts about software-related technology.</description><language>en</language><generator>Hugo</generator><atom:link href="https://jeffbailey.us/categories/learn-x---development---command-line/rss.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Sat, 07 Jun 2025 00:00:00 +0000</lastBuildDate><item><title>Learn Neovim</title><link>https://jeffbailey.us/blog/2025/06/07/learn-neovim/</link><guid isPermaLink="true">https://jeffbailey.us/blog/2025/06/07/learn-neovim/</guid><pubDate>Sat, 07 Jun 2025 00:00:00 +0000</pubDate><dc:creator>Jeff Bailey</dc:creator><category>Learn X - Development - Command Line</category><description><![CDATA[<style>
  .command-search {
    max-width: 800px;
    margin: 2rem auto;
    padding: 1rem;
  }
  
  .command-search-input {
    width: 100%;
    padding: 0.75rem;
    font-size: 1.1rem;
    border: 2px solid var(--border);
    border-radius: 8px;
    margin-bottom: 1rem;
  }
  
  #command-search-input {
    color: var(--content) !important;
    background-color: var(--background) !important;
  }
  
  .command-results {
    margin-top: 1rem;
    max-height: 500px;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: 8px;
    color: var(--content) !important;
    background-color: var(--background) !important;
  }
  
  .command-result {
    padding: 0.75rem;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 1rem;
    cursor: pointer;
    transition: background-color 0.2s ease;
  }
  
  .command-result:hover {
    background-color: var(--code-bg);
  }
  
  .command-keys {
    font-family: monospace;
    font-size: 1.1rem;
    min-width: 4rem;
    text-align: center;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
  }
  
  .command-keys.keyboard {
    background-color: var(--code-bg);
  }
  
  .command-keys.command {
    background-color: var(--primary);
    color: var(--background);
  }
  
  .command-keys.shortcut {
    background-color: var(--secondary);
    color: var(--background);
  }
  
  .command-desc {
    flex: 1;
    color: var(--secondary);
  }
  
  .command-category {
    font-weight: 600;
    min-width: 150px;
    color: var(--primary);
  }
  
  .no-results {
    padding: 1rem;
    text-align: center;
    color: var(--secondary);
  }
  
  @media (max-width: 768px) {
    .command-result {
      flex-direction: column;
      align-items: flex-start;
      gap: 0.5rem;
    }
    
    .command-category {
      min-width: auto;
    }
  }
</style>

<div class="command-search">
  <input type="text" 
         id="command-search-input" 
         placeholder="Search for commands (e.g., delete, window, tab)..." 
         class="command-search-input"
         aria-label="Search for commands">
  <div id="command-results" class="command-results"></div>
</div>

<script>

window.addEventListener('load', function() {
  const searchInput = document.getElementById('command-search-input');
  const resultsDiv = document.getElementById('command-results');

  
  function extractCommands() {
    const commands = [];
    const content = document.querySelector('article');
    
    if (!content) {
      return commands;
    }

    
    const listItems = content.querySelectorAll('li');

    listItems.forEach(item => {
      const text = item.textContent.trim();

      
      const emElement = item.querySelector('em');
      if (emElement) {
        const keys = emElement.textContent.trim();
        
        const description = text.replace(emElement.textContent, '').replace('-', '').trim();
        
        
        let category = 'General';
        let currentElement = item;
        
        
        function findNearestHeading(element) {
          
          let current = element;
          while (current && !current.matches('h2, h3, h4')) {
            current = current.previousElementSibling;
          }
          
          
          if (!current) {
            current = element.parentElement;
            while (current && !current.matches('h2, h3, h4')) {
              current = current.previousElementSibling;
            }
          }
          
          return current;
        }
        
        
        function findParentHeading(element) {
          let current = element;
          while (current && !current.matches('h2')) {
            current = current.previousElementSibling;
          }
          return current;
        }
        
        
        const nearestHeading = findNearestHeading(currentElement);
        
        if (nearestHeading) {
          if (nearestHeading.matches('h3, h4')) {
            const parentHeading = findParentHeading(nearestHeading);
            if (parentHeading) {
              
              category = nearestHeading.textContent.trim().replace('#', '');
            } else {
              category = nearestHeading.textContent.trim();
            }
          } else {
            category = nearestHeading.textContent.trim();
          }
        }

        commands.push({
          keys: keys,
          description: description,
          category: category,
          element: item,
          type: 'keyboard'
        });
      }
    });
    
    return commands;
  }

  function searchCommands(searchTerm) {
    const normalizedSearch = searchTerm.toLowerCase().trim();
    const commands = extractCommands();
    
    if (!normalizedSearch) {
      resultsDiv.innerHTML = '';
      return;
    }

    const results = commands.filter(cmd => 
      cmd.keys.toLowerCase().includes(normalizedSearch) ||
      cmd.description.toLowerCase().includes(normalizedSearch) ||
      cmd.category.toLowerCase().includes(normalizedSearch)
    );
    
    if (results.length > 0) {
      resultsDiv.innerHTML = results
        .map(cmd => `
          <div class="command-result" data-command="${cmd.keys}" data-type="${cmd.type}">
            <span class="command-keys ${cmd.type}">${cmd.keys}</span>
            <span class="command-category">${cmd.category}</span>
            <span class="command-desc">${cmd.description}</span>
          </div>
        `)
        .join('');

      
      resultsDiv.querySelectorAll('.command-result').forEach(result => {
        result.addEventListener('click', function() {
          const command = this.dataset.command;
          const type = this.dataset.type;
          const originalElement = commands.find(cmd => cmd.keys === command && cmd.type === type)?.element;
          
          if (originalElement) {
            
            window.getSelection().removeAllRanges();
            
            
            const range = document.createRange();
            range.selectNode(originalElement);
            
            
            const selection = window.getSelection();
            selection.addRange(range);
            
            
            originalElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
          }
        });
      });
    } else {
      resultsDiv.innerHTML = '<div class="no-results">No commands found matching your search</div>';
    }
  }

  if (searchInput && resultsDiv) {
    
    setTimeout(() => searchCommands(''), 500);

    
    searchInput.addEventListener('input', function(e) {
      searchCommands(e.target.value);
    });

    
    searchInput.addEventListener('keydown', function(e) {
      if (e.key === 'Enter') {
        const firstResult = resultsDiv.querySelector('.command-result');
        if (firstResult) {
          firstResult.click(); 
        }
      }
    });
  }
});
</script> 
<h2 id="why-neovim-exists">Why Neovim Exists</h2>
<p>Early in my career, Vim introduced me to text editing with modal editing, commands, and home row typing. But, over time, its technical debt and complex codebase hindered updates.</p>]]></description></item></channel></rss>