Skip to Content

Tipjar

    Context Managers for Debugging (Python)

    A small helper I use to debug some python programs:

    from contextlib import contextmanager
    
    @contextmanager
    def debug_error():
        try:
            yield
        except Exception as e:
            breakpoint()
            quit()
    
    ### usage
    
    with debug_error():
      x = 1
      y = 0
      x/y # x and y will be avail in pdb
    

    You can also put things before the yield (which will run before the with block), and after it (to run at the end of the block.) Anything put after it will run at the end of the block. See @contextmanager for more info.

    Notes


    Path Objects (Python)

    Python 3.4 added path objects, but most people still don’t know about them. They simplify a lot of file operations:

    ### Without pathlib
    
    path = "path/to/file"
    
    # parent dir
    os.path.dirname(path)
    
    # file suffix
    os.path.splitext(path)[1]
    
    # read file
    with open(path) as f:
      x = f.read()
    
    
    ### With pathlib
    
    path = pathlib.Path("path/to/file")
    
    # parent dir
    path.parent
    
    # file suffix
    path.suffix
    
    # read file
    x = path.read_text()
    

    Paths are also OS-independent, so the same code will generally work on both Windows and Unix.


    LoadLocal (vim)

    This one’s in Lua because I use Neovim, but it should be directly translatable to VimScript.

    I often need to rerun the same commands in a specific buffer. For example, I might regularly run one command to expand an XML metafile, and then another to run one of the expanded outputs.

    function LoadLocal(local_cmd)
      vim.b.local_cmd = local_cmd
    end
    
    function RunLocal()
      vim.cmd(vim.b.local_cmd)
    end
    
    vim.cmd [[command! -nargs=1 LoadLocal call v:lua.LoadLocal(<f-args>)]]
    vim.keymap.set('n', 'gxl', RunLocal, {silent = true})
    

    Use it like this:

    :LoadLocal !python %
    

    Then, for that buffer and only that buffer, typing gxl will call python on the file.

    Notes

    I have a few different map leaders. The spacebar is my default <leader> for most mappings, but I also use \ for some navigational commands, gx for triggering scripts, and ; for insert-mode commands, like

    inoremap ;r <c-R>+
    


    File Watcher (PowerShell)

    I wanted to run a script every time a file changed. There’s a bunch of tools to do this for Linux, but I’m on Windows (because reasons). I found a PowerShell module, installed it, and got to work.

    function Enter-Watcher {
      Param (
        [PSDefaultValue(Help="*")]
        $Filter="*",
        $Path=".",
        $SourceIdentifier="watcher-event",
        [Parameter(Mandatory=$true, Position=0)]
        $ScriptBlock
      )
    
      #Cleanup of previous uses. Remove past watchers of this type, to eliminate double-events
      $e = "$SourceIdentifier-emit" 
      Remove-Job -name $e,$SourceIdentifier -Force 2>$null # -Force removes not-stopped jobs too
      Remove-FileSystemWatcher -SourceIdentifier $SourceIdentifier
    
      $fs = New-FileSystemWatcher -SourceIdentifier $SourceIdentifier -Path $Path -Filter $Filter -Action {
        if($event.messageData.ChangeType -eq "Changed") {
          $x = "$($event.SourceIdentifier)-emit"
          New-Event -SourceIdentifier $x -MessageData $event.messageData.fullpath
        }
      }
    
      $job = Register-EngineEvent -SourceIdentifier $e -Action $Scriptblock
      while($true) {
        receive-job $job
      }
    } 
    
    function Remove-AllWatchers {
      Get-FileSystemWatcher | Remove-FileSystemWatcher
    }
    

    Call it like: