My Technical Notes

Tuesday, 5 May 2015

PowerShell: Defining Import/Export functions for OrgTables

Emacs has a major mode called `org-mode`. Within this, you can quickly define a text table, for example:


| Forename | Surname  | Party         |
|----------+----------+---------------|
| Nick     | Clegg    | Lib Dems      |
| Ed       | Miliband | Labour        |
| David    | Cameron  | Conservatives |

Below I have defined two functions:

  • `Import-OrgTable` - a function, given a path to an `.org` file, it will import the data from it, much like how `Import-Csv` works.
  • `Export-OrgTable` - a function which will output a set of objects to a file in the `.org` format, much like how `Export-Csv` works.

Function ConverOrgTableToCsv([string]$orgTablePath, [string]$outCsvPath) {
    $csv_content = Get-Content $path_ | % {
        $line = $_.ToString().Trim();
        if (-not ($line.StartsWith("|-") -and $line.EndsWith(("-|")))) {
            $s1 = [Regex]::Replace($line, "^\s*\|\s*", "")
            $s2 = [Regex]::Replace($s1, "\s*\|\s*$", "")
            $elems = [regex]::Split($s2, "\s*\|\s*") | % { if ($_.Contains(",")) { "`"$_`"" } else { $_ } }

            [string]::Join(",", $elems);
        }
    }

    $csv_content | Out-File -FilePath $outCsvPath
}

# http://stackoverflow.com/questions/885349/how-to-write-a-powershell-script-that-accepts-pipeline-input
# add something to do with accepting a file fro
Function Import-OrgTable {
    param(  
    [Parameter(Position=0,Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
    [Alias('FullName')]
    [String[]]$FilePath
    ) 

    process {
       foreach ($path in $FilePath)
       {
            $path_ = Resolve-Path $path
            $tempPath = Join-Path (Split-Path $path_) ([Guid]::NewGuid().ToString() + ".csv")

            ConverOrgTableToCsv $path_ $tempPath

            Import-Csv $tempPath

            Remove-Item $tempPath
       }
    }
}

# http://stackoverflow.com/questions/885349/how-to-write-a-powershell-script-that-accepts-pipeline-input
# add something to do with accepting a file fro
Function Export-OrgTable {
    param(
    [Parameter(Mandatory=$true)][string]$Path,
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]$ObjectSet
    ) 

    if ($input) {
        $ObjectSet = $input;
    }

    $lines = ($ObjectSet | Format-Table -AutoSize | Out-String) -split [System.Environment]::NewLine | Where { $_ }

    if (($lines) -and ($lines.Length -ge 2) -and ($lines[1] -match '^(\s|-)+$')) {
        $ind_length = [Regex]::Matches($lines[1], '(-)+\s*') | Select Index, Length
        $splitLine = { param($line) $ind_length | Foreach { $line.Substring($_.Index, $_.Length)  } }

        & {
            $formatLine = { "| $( (& $splitLine $_) -join ' | ' ) |" }

            $lines | Select -Index 0 | Foreach $formatLine
            $lines | select -Index 1 | Foreach { "|-$( (& $splitLine $_).Replace(' ', '-') -join '-+-' )-|" }
            $lines | Select -Skip 2 | Foreach $formatLine
        } | Out-File $Path
    }
}

Export-ModuleMember -Function '*-*'

No comments: