Thursday, December 16, 2010

Delicious Export HTML: Show Tags

There are rumors going around that Yahoo! is shutting down their Delicious social bookmarking site, and there are already a couple of posts describing how to preserve your bookmarks.  One of the most valuable aspects of bookmarks are your tags, and unfortunately when you export your bookmarks from Delicious, the HTML page that you download doesn't display the tags.

If it did, you would at least be able to open the web page and search for a specific tag.  The tags are there in the HTML source, but they aren't visible on the page.

Here's how to modify the page source to make them visible.  First, log in to Delicious, and go to the Export page in Settings.  Download the export file and save it.

Next, open the file in gVim (You can download gVim here).

Enter the following command.  You can either do this by typing it in, or by copying it from this web page (starting after the colon), typing the colon character ":", and then pressing Ctrl+V.  Here's the command:

:%s/\(<A HREF="[^"]*" .* TAGS="\([^"]*\)">[^<]*<\/A>\(\n.*\)\?\)/\1\r<DD><I>\2<\/I>/g


Press Enter.  This will apply the command.

:wq
 Next, save the file and exit gVim.  You can do that with the ":wq" command, but you can also just click the graphical "Save" icon.


Wednesday, December 08, 2010

Twitpic-to-Posterous Script: Another Update

A while ago I wrote a script to import my Twitpic photo posts to Posterous and posted it on this blog.

Even though Posterous now supplies their own working transfer tool, it has its limitations.  One person who tried that tool was unsatisfied, and tried my script.  He really liked the results, but he noticed some drawbacks to my script as well.  Here's what's new in my script v1.3.1:
  • New feature by request - #hashtags and @username mentions are now linked to the appropriate Twitter page in the body of the Posterous post.
  • Fix - issue where Twitpic now truncates the tweet text in the HTML title.  Switched to using the image alt text from the full page.  
  • Fix - Twitpic started escaping single and double quotes in the tweet text, which were showing up uninterpreted in the Posterous titles.  The script now handles them correctly.
  • Other changes
    • Only download the Full images by default (Scaled and thumbnails can be enabled by setting flags.)
    • Print an error message and pause for 5 seconds if a download fails (Twitpic was being unreliable during my testing.)
    • Other miscellaneous fixes and tweaks
Special thanks to @RyanMeray!
  • Update (v1.3.2): better regular expressions for @username and #hashtag formats. 
  • Update (v1.3.4): now optionally adds hashtags as post tags.
You can get the latest version here.

    Wednesday, December 01, 2010

    Dropbox Sync Script

    Recently, I started using Steam, and while Steam can install each of your games on each of your computers, it doesn't keep the game saves in sync.  I wanted to be able to pick up where I had left off on any computer I wanted, not needing to worry about copying over save files, so I turned to Dropbox, which I've been using for a while. 

    I had created a set of batch scripts that I used on Windows to set up the sync folders, but since I was adding several folders, and the number of scripts was getting to be large, I decided to combine them all into a single flexible and streamlined script.  I also decided to make it as generic as possible, so that other people could use it with minimal fuss.  Basically the script has a function that moves files and folders located outside of the Dropbox folder inside, and then creates a symlink (or folder junction), so that the program accessing the files doesn't need to be reconfigured in order to keep accessing the files.  If the item is already in the Dropbox folder, the original is kept under a different name, and a link is created to the existing synced content.  If the item doesn't exist in either place, it gets created in Dropbox, and linked to in the specified location.

    The script is populated with things that I want synced, which will probably be different from what you want to sync, but it should be a simple matter to change that.  If you add items, the script is set up so that you can re-run it without creating more and more symlinks.

    It's worth noting that the mklink command requires Windows Vista or later.  If you're running an earlier version such as XP, it will use the linkd command, which comes with the Windows 2003 Resource Kit. (You don't need to be running 2003 to install it.)

    So, without further ado, here is the script:
    @echo off
    :: This script creates symlinks (NTFS junctions) in order to sync the contents via Dropbox
    :: Some of these items require Administrator privileges to execute because of where the items are located.
    
    :: Copyright 2010 Tim "burndive" of http://burndive.blogspot.com/ and http://tuxbox.blogspot.com/
    :: This software is licensed under the Creative Commons GNU GPL version 2.0 or later.
    :: License informattion: http://creativecommons.org/licenses/GPL/2.0/
    :: This script was obtained from here:
    :: http://tuxbox.blogspot.com/2010/12/dropbox-sync-script.html
    
    :: Set this to your Steam user ID
    set STEAM_USER=burndive
    
    :: The path to your Documents folder
    set DOCUMENTS=%USERPROFILE%\My Documents
    if exist "%USERPROFILE%\Documents" (
      set DROPBOX=%USERPROFILE%\Documents
    )
    
    :: The path to your Dropbox folder
    set DROPBOX=%DOCUMENTS%\My Dropbox
    if exist "%USERPROFILE%\Dropbox" (
      set DROPBOX=%USERPROFILE%\Dropbox
    )
    
    :: Determine which command to use for making Folder Junctions
    ver | findstr "5." > nul
    if errorlevel 1 (
      :: This requires Windows Vista or later
      set JUNCTION_CMD=mklink /j
    ) else (
      :: This requires the Windows 2003 Resource Kit Tools
      set JUNCTION_CMD=linkd
    )
    
    :: Find the correct Flash SharedObjects folder name if localhost subfolder exists
    set FLASH_LOCAL=
    for /F "tokens=*" %%I in ('dir /b "%APPDATA%\Macromedia\Flash Player\#SharedObjects"') do (
      if exist "%APPDATA%\Macromedia\Flash Player\#SharedObjects\%%I\localhost" (
        set FLASH_LOCAL=%APPDATA%\Macromedia\Flash Player\#SharedObjects\%%I\localhost
      )
    )
    
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :: The following items require only User privileges to execute
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    :: Make localhost Flash Shared Objects dir architecture neutral
    if not "%FLASH_LOCAL%" == "" (
      if exist "%FLASH_LOCAL%\Program Files (x86)" (
        call:LinkFolder "%FLASH_LOCAL%", "Program Files", "%FLASH_LOCAL%\Program Files (x86)"
      )
    )
    
    :: Digital Blasphemy wallpapers
    call:LinkFolder "%USERPROFILE%\Pictures\wallpaper", "db-fs", "%DROPBOX%\images\digital-blasphemy\db-fs"
    call:LinkFolder "%USERPROFILE%\Pictures\wallpaper", "db-ws", "%DROPBOX%\images\digital-blasphemy\db-ws"
    call:LinkFolder "%USERPROFILE%\Pictures\wallpaper", "db-preview", "%DROPBOX%\images\digital-blasphemy\db-preview"
    
    :: Images
    call:LinkFolder "%USERPROFILE%\Pictures", "images", "%DROPBOX%\images"
    
    :: Pidgin Instant Messenger
    call:LinkFolder "%APPDATA%\.purple", "icons", "%DROPBOX%\app-files\pidgin\icons"
    call:LinkFolder "%APPDATA%\.purple", "logs", "%DROPBOX%\app-files\pidgin\logs"
    
    :: DVRMSToolbox Commercials XML files
    call:LinkFolder "%PUBLIC%\DvrmsToolbox", "CommercialsXml", "%DROPBOX%\app-files\CommercialsXml"
    
    ::::::::::::::::::::::
    :: Humble Bundle Games
    ::::::::::::::::::::::
    :: Penumbra Overture
    call:LinkFolder "%DOCUMENTS%\Penumbra Overture\Episode1", "save", "%DROPBOX%\app-files\game-saves\penumbra-overture"
    :: Samarost2 : TODO
    :: World of Goo
    call:LinkFolder "%LOCALAPPDATA%\2DBoy", "WorldOfGoo", "%DROPBOX%\app-files\game-saves\world-of-goo"
    :: Aquaria : TODO
    :: Gish : TODO
    :: Lugaru : TODO
    
    ::::::::::::::::::::::::
    :: Humble Bundle 2 Games
    ::::::::::::::::::::::::
    :: Braid
    call:LinkFolder "%APPDATA%", "Braid", "%DROPBOX%\app-files\game-saves\braid"
    :: Machinarium
    if not "%FLASH_LOCAL%" == "" (
      if exist "%FLASH_LOCAL%\Program Files" (
        call:LinkFolder "%FLASH_LOCAL%\Program Files\Machinarium", "machinarium.exe", "%DROPBOX%\app-files\game-saves\machinarium"
      )
    )
    :: Osmos
    call:LinkFolder "%DOCUMENTS%", "Osmos", "%DROPBOX%\app-files\game-saves\osmos"
    :: Cortex Command : TODO
    :: Revenge of the Titans HIB
    call:LinkFolder "%USERPROFILE%\Revenge of the Titans 1.71", "slots", "%DROPBOX%\app-files\game-saves\revenge-of-the-titans-1.71"
    call:LinkFolder "%USERPROFILE%\Revenge of the Titans 1.72", "slots", "%DROPBOX%\app-files\game-saves\revenge-of-the-titans-1.72"
    
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :: The following items require Administrator privileges to execute
    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    :: Eclipse workspace
    call:LinkFolder "%USERPROFILE%", "workspace", "%DROPBOX%\app-files\workspace"
    
    :: gVim config file
    call:LinkFile "%USERPROFILE%", "_gvimrc", "%DROPBOX%\config\windows\_gvimrc"
    
    :: Steam Game save folders
    if exist "%PROGRAMFILES(X86)%" (
      :: Note: The caret is an escape character
      set STEAM_DIR=C:\Program Files ^(x86^)\Steam\steamapps
    ) else (
      set STEAM_DIR=%PROGRAMFILES%\Steam\steamapps
    )
    call:LinkFolder "%STEAM_DIR%\%STEAM_USER%\half-life 2\hl2", "SAVE", "%DROPBOX%\app-files\game-saves\half-life-2-steam"
    call:LinkFolder "%STEAM_DIR%\%STEAM_USER%\half-life 2 episode one\episodic", "SAVE", "%DROPBOX%\app-files\game-saves\half-life-2-ep1-steam"
    call:LinkFolder "%STEAM_DIR%\%STEAM_USER%\half-life 2 episode two\ep2", "SAVE", "%DROPBOX%\app-files\game-saves\half-life-2-ep2-steam"
    call:LinkFolder "%STEAM_DIR%\%STEAM_USER%\half-life 2 lostcoast\lostcoast", "SAVE", "%DROPBOX%\app-files\game-saves\half-life-2-lostcoast-steam"
    call:LinkFolder "%STEAM_DIR%\%STEAM_USER%\portal\portal", "SAVE", "%DROPBOX%\app-files\game-saves\portal-steam"
    
    :: Pause so the user can review output
    pause
    
    :: End of execution
    goto:eof
    
    ::::::::::::
    :: Functions
    ::::::::::::
    
    :LinkFolder
    setlocal
    :: Arguments
    set LINK_PATH=%~1
    set LINK_NAME=%~2
    set TARGET=%~3
    ::echo Link: %LINK_PATH%\%LINK_NAME%
    ::echo Target: %TARGET%
    
    if not exist "%LINK_PATH%" (
      mkdir "%LINK_PATH%"
    )
    cd "%LINK_PATH%"
    :: If the folder is already a link, just delete it
    dir | findstr /i "%LINK_NAME%" | findstr "<JUNCTION>" > NUL
    if not errorlevel 1 (
      rmdir "%LINK_NAME%"
    )
    if exist "%LINK_NAME%" (
      if exist "%TARGET%" (
        echo Backing up conflicting copy
        move "%LINK_NAME%" "%LINK_NAME%-orig"
      ) else (
        :: Move the original if target does not exist
        echo Moving original folder to link location
        echo move "%LINK_NAME%" "%TARGET%"
        move "%LINK_NAME%" "%TARGET%"
      )
    ) else (
      if not exist "%TARGET%" (
        :: If neither exist, create target
        echo Creating target folder
        mkdir "%TARGET%"
      )
    )
    %JUNCTION_CMD% "%LINK_NAME%" "%TARGET%"
    
    endlocal
    goto:eof
    
    :LinkFile
    setlocal
    :: Arguments
    set LINK_PATH=%~1
    set LINK_NAME=%~2
    set TARGET=%~3
    ::echo Link: %LINK_PATH%\%LINK_NAME%
    ::echo Target: %TARGET%
    
    if not exist "%LINK_PATH%" (
      mkdir "%LINK_PATH%"
    )
    cd "%LINK_PATH%"
    :: If the folder is already a link, just delete it
    dir | findstr /i "%LINK_NAME%" | findstr "<SYMLINK>" > NUL
    if not errorlevel 1 (
      del "%LINK_NAME%"
    )
    if exist "%LINK_NAME%" (
      if exist "%TARGET%" (
        echo Backing up conflicting copy
        move "%LINK_NAME%" "%LINK_NAME%-orig"
      ) else (
        :: Move the original if target does not exist
        echo Moving original file to target location
        move "%LINK_NAME%" "%TARGET%"
      )
    ) else (
      if not exist "%TARGET%" (
        :: If neither exist, create target
        echo Creating empty target file
        echo "" > "%TARGET%"
      )
    )
    :: linkd will not work for files, only folders
    mklink "%LINK_NAME%" "%TARGET%"
    
    endlocal
    goto:eof
    CC-GNU GPL
    This software is licensed under the CC-GNU GPL version 2.0 or later.

    PS: If you use my code, I appreciate comments to let me know, and any feedback you may have, especially if it's not working right for you, but also just to say thanks.

    For convenience, you can download this script from my server.