PersonalLookup.psm1

#requires -Version 5.1

# Module for personal text lookup by alias
# Provides quick access to stored information via clipboard

# Configuration file location
$Script:ConfigPath = Join-Path -Path $HOME -ChildPath "Documents\PersonalLookup_config.json"

# Default database file location
$Script:DbPath = Join-Path -Path $HOME -ChildPath "Documents\db.txt"

# Load custom path from configuration if it exists
if (Test-Path -Path $Script:ConfigPath) {
    try {
        $config = Get-Content -Path $Script:ConfigPath -Raw | ConvertFrom-Json
        if ($config.DbPath -and (Test-Path -Path $config.DbPath)) {
            $Script:DbPath = $config.DbPath
            # Using Write-Host instead of Write-Verbose to ensure visibility
            Write-Host "PersonalLookup: Using custom database path: $Script:DbPath" -ForegroundColor Cyan
        }
    }
    catch {
        Write-Warning "Could not read configuration file. Using default database path."
    }
}
else {
    Write-Host "PersonalLookup: Using default database path: $Script:DbPath" -ForegroundColor Gray
}

# Private encryption functions
function Protect-Value {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Value
    )
    
    if ([string]::IsNullOrEmpty($Value)) { return "" }
    
    # Encrypt the value using DPAPI via SecureString
    $encryptedValue = ConvertFrom-SecureString -SecureString (ConvertTo-SecureString -String $Value -AsPlainText -Force)
    
    return $encryptedValue
}

function Unprotect-Value {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$EncryptedValue
    )
    
    if ([string]::IsNullOrEmpty($EncryptedValue)) { return "" }
    
    try {
        # Try to decrypt - if this succeeds, it was encrypted
        $secureValue = ConvertTo-SecureString -String $EncryptedValue -ErrorAction Stop
        $bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureValue)
        try {
            $decryptedValue = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
            return $decryptedValue
        }
        finally {
            [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
        }
    }
    catch {
        # If decryption fails, assume it wasn't encrypted and return as-is
        Write-Verbose "Value doesn't appear to be encrypted or cannot be decrypted."
        return $EncryptedValue
    }
}

# Function to safely migrate existing database to encrypted format
function ConvertTo-EncryptedDatabase {
    [CmdletBinding()]
    param()
    
    # Check if database exists
    if (-not (Test-Path -Path $Script:DbPath)) {
        Write-Verbose "No database to encrypt."
        return
    }
    
    # Read existing content
    $content = Get-Content -Path $Script:DbPath
    $newContent = @()
    $encryptedCount = 0
    
    foreach ($line in $content) {
        if ($line -match "^(.+?)=(.*)$") {
            $key = $Matches[1]
            $value = $Matches[2]
            
            # Try to decrypt to check if already encrypted
            try {
                ConvertTo-SecureString -String $value -AsPlainText -Force -ErrorAction Stop
                # If we get here, it's already encrypted
                $newContent += $line
            }
            catch {
                # Value is not encrypted, so encrypt it
                $encryptedValue = Protect-Value -Value $value
                $newContent += "$key=$encryptedValue"
                $encryptedCount++
            }
        }
        else {
            # Keep lines that don't match pattern
            $newContent += $line
        }
    }
    
    if ($encryptedCount -gt 0) {
        # Write encrypted content back to file
        Set-Content -Path $Script:DbPath -Value $newContent
        Write-Verbose "Encrypted $encryptedCount values in the database."
    }
}

# Run encryption migration when module loads
ConvertTo-EncryptedDatabase

function Get-Lookup {
    <#
    .SYNOPSIS
        Retrieves a value by key and copies it to clipboard
    .DESCRIPTION
        Looks up a key in the database and copies its value to clipboard
    .PARAMETER Key
        The key to look up
    .PARAMETER NoCopy
        If specified, doesn't copy to clipboard, just displays the value
    .PARAMETER Show
        If specified, displays the value instead of just copying silently
    .PARAMETER NoAutoClipboardClear
        If specified, doesn't automatically clear clipboard after 70 seconds
    .EXAMPLE
        Get-Lookup iban
        # Silently copies IBAN to clipboard, clears after 70 seconds
    .EXAMPLE
        dbget iban -Show -NoAutoClipboardClear
        # Shows the IBAN, copies it to clipboard, and doesn't auto-clear
    #>

    [CmdletBinding()]
    [Alias("dbget")]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Key,
        
        [Parameter()]
        [switch]$NoCopy,
        
        [Parameter()]
        [switch]$Show,
        
        [Parameter()]
        [switch]$NoAutoClipboardClear
    )
    
    # Ensure database file exists
    if (-not (Test-Path -Path $Script:DbPath)) {
        Write-Error "Database file not found at $Script:DbPath"
        return
    }
    
    # Read all lines from the file
    $content = Get-Content -Path $Script:DbPath
    
    # Find the line with the key
    $line = $content | Where-Object { $_ -match "^$Key=" }
    
    if ($line) {
        # Extract value (everything after the first = and before optional |)
        if ($line -match "^$Key=(.+?)(?:\|(.+))?$") {
            $encryptedValue = $Matches[1]
            $shortcut = $Matches[2]  # Will be $null if no shortcut exists
            
            # Decrypt the value
            $value = Unprotect-Value -EncryptedValue $encryptedValue
            
            # Copy to clipboard if not prohibited
            if (-not $NoCopy) {
                Set-Clipboard -Value $value
                
                # Setup auto-clearing of clipboard after 70 seconds
                if (-not $NoAutoClipboardClear) {
                    Start-Job -ScriptBlock {
                        # Wait for 70 seconds
                        Start-Sleep -Seconds 70
                        
                        # Clear the clipboard
                        Set-Clipboard -Value ""
                    } | Out-Null
                    
                    Write-Verbose "Clipboard will be cleared after 70 seconds"
                }
            }
            
            # Show value if requested
            if ($Show) {
                Write-Output "$value"
            }
                        
            # Run shortcut if it exists
            if ($shortcut -and -not $NoCopy) {
                try {
                    Write-Verbose "Running shortcut: $shortcut"
                    Start-Process -FilePath $shortcut
                }
                catch {
                    Write-Warning "Failed to run shortcut: $shortcut. Error: $_"
                }
            }
            exit
        }
        else {
            # Extract value using the old format (just in case)
            $encryptedValue = $line -replace "^$Key=", ""
            
            # Decrypt the value
            $value = Unprotect-Value -EncryptedValue $encryptedValue
            
            # Copy to clipboard if not prohibited
            if (-not $NoCopy) {
                Set-Clipboard -Value $value
                
                # Setup auto-clearing of clipboard after 70 seconds
                if (-not $NoAutoClipboardClear) {
                    Start-Job -ScriptBlock {
                        # Wait for 70 seconds
                        Start-Sleep -Seconds 70
                        
                        # Clear the clipboard
                        Set-Clipboard -Value ""
                    } | Out-Null
                    
                    Write-Verbose "Clipboard will be cleared after 70 seconds"
                }
            }
            
            # Show value if requested
            if ($Show) {
                Write-Output "$value"
            }
            else {
                exit
            }
        }
    }
    else {
        Write-Error "Key '$Key' not found in the database."
    }
}

function Set-Lookup {
    <#
    .SYNOPSIS
        Adds or updates a key-value pair in the database
    .DESCRIPTION
        Sets a value for a key in the database, creating or updating as needed
    .PARAMETER Key
        The key to set
    .PARAMETER Value
        The value to store
    .PARAMETER Shortcut
        Optional path to a shortcut or executable to run after copying the value
    .EXAMPLE
        Set-Lookup -Key "newkey" -Value "new value to store"
    .EXAMPLE
        dbset newkey "new value to store" "C:\path\to\app.exe"
    #>

    [CmdletBinding()]
    [Alias("dbset")]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Key,
        
        [Parameter(Mandatory = $true, Position = 1)]
        [string]$Value,
        
        [Parameter(Mandatory = $false, Position = 2)]
        [string]$Shortcut
    )
    
    # Create the file if it doesn't exist
    if (-not (Test-Path -Path $Script:DbPath)) {
        New-Item -Path $Script:DbPath -ItemType File -Force | Out-Null
        Write-Verbose "Created new database file at $Script:DbPath"
    }
    
    # Read existing content
    $content = @()
    if (Test-Path -Path $Script:DbPath) {
        $content = Get-Content -Path $Script:DbPath
    }
    
    # Encrypt the value before storing
    $encryptedValue = Protect-Value -Value $Value
    
    # Check if key already exists
    $keyExists = $false
    $newContent = @()
    
    foreach ($line in $content) {
        if ($line -match "^$Key=") {
            # Replace existing key
            if ($Shortcut) {
                $newContent += "$Key=$encryptedValue|$Shortcut"
            }
            else {
                $newContent += "$Key=$encryptedValue"
            }
            $keyExists = $true
        }
        else {
            # Keep existing line
            $newContent += $line
        }
    }
    
    # Add new key if it doesn't exist
    if (-not $keyExists) {
        if ($Shortcut) {
            $newContent += "$Key=$encryptedValue|$Shortcut"
        }
        else {
            $newContent += "$Key=$encryptedValue"
        }
    }

    # Write back to file
    Set-Content -Path $Script:DbPath -Value $newContent
    
    if ($Shortcut) {
        Write-Output "Key '$Key' has been set successfully with shortcut: $Shortcut"
    }
    else {
        Write-Output "Key '$Key' has been set successfully."
    }

    # Clear the last command from history to avoid storing sensitive information
    Clear-History -Count 1

    # Ask if user wants to add another entry
    $addAnother = Read-Host "Add another entry? (y/N): "
    if ($addAnother.ToLower() -ne 'y') {
        exit
    }
}

function Remove-Lookup {
    <#
    .SYNOPSIS
        Removes a key-value pair from the database
    .DESCRIPTION
        Deletes a key and its associated value from the database
    .PARAMETER Key
        The key to remove
    .EXAMPLE
        Remove-Lookup -Key "oldkey"
    .EXAMPLE
        dbremove oldkey
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    [Alias("dbremove")]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Key
    )
    
    # Ensure database file exists
    if (-not (Test-Path -Path $Script:DbPath)) {
        Write-Error "Database file not found at $Script:DbPath"
        return
    }
    
    # Read existing content
    $content = Get-Content -Path $Script:DbPath
    
    # Check if key exists
    $keyExists = $false
    $newContent = @()
    
    foreach ($line in $content) {
        if ($line -match "^$Key=") {
            $keyExists = $true
            # Skip this line to remove it
        }
        else {
            # Keep existing line
            $newContent += $line
        }
    }
    
    if (-not $keyExists) {
        Write-Error "Key '$Key' not found in the database."
        return
    }
    
    # Confirm before removing
    if ($PSCmdlet.ShouldProcess("Key '$Key'", "Remove")) {
        # Write back to file
        Set-Content -Path $Script:DbPath -Value $newContent
        Write-Output "Key '$Key' has been removed successfully."
    }
}

function Show-AllLookups {
    <#
    .SYNOPSIS
        Shows all keys in the database
    .DESCRIPTION
        Displays a list of all keys stored in the database
    .PARAMETER IncludeValues
        If specified, shows values alongside keys
    .PARAMETER IncludeShortcuts
        If specified, shows shortcuts alongside keys and values
    .EXAMPLE
        Show-AllLookups
    .EXAMPLE
        dbshow -IncludeValues -IncludeShortcuts
    #>

    [CmdletBinding()]
    [Alias("dbshow")]
    param (
        [Parameter()]
        [switch]$IncludeValues,
        
        [Parameter()]
        [switch]$IncludeShortcuts
    )
    
    # Ensure database file exists
    if (-not (Test-Path -Path $Script:DbPath)) {
        Write-Error "Database file not found at $Script:DbPath"
        return
    }
    
    # Read all lines from the file
    $content = Get-Content -Path $Script:DbPath
    
    if ($content.Count -eq 0) {
        Write-Output "The database is empty."
        return
    }
    
    Write-Output "Available keys in database:"
    
    if ($IncludeValues) {
        # Show keys with values and optionally shortcuts
        foreach ($line in $content) {
            if ($line -match "^(.+?)=(.+?)(?:\|(.+))?$") {
                $key = $Matches[1]
                $encryptedValue = $Matches[2]
                $shortcut = $Matches[3]  # Will be $null if no shortcut exists
                
                # Decrypt the value for display
                $decryptedValue = Unprotect-Value -EncryptedValue $encryptedValue
                
                if ($IncludeShortcuts -and $shortcut) {
                    [PSCustomObject]@{
                        Key      = $key
                        Value    = $decryptedValue
                        Shortcut = $shortcut
                    }
                }
                else {
                    [PSCustomObject]@{
                        Key   = $key
                        Value = $decryptedValue
                    }
                }
            }
            # Handle the old format without shortcut
            elseif ($line -match "^(.+?)=(.+)$") {
                $key = $Matches[1]
                $encryptedValue = $Matches[2]
                
                # Decrypt the value for display
                $decryptedValue = Unprotect-Value -EncryptedValue $encryptedValue
                
                [PSCustomObject]@{
                    Key   = $key
                    Value = $decryptedValue
                }
            }
        }
    }
    else {
        # Show only keys
        foreach ($line in $content) {
            if ($line -match "^(.+?)=") {
                $Matches[1]
            }
        }
    }
}

function Set-LookupDbPath {
    <#
    .SYNOPSIS
        Sets the path to the lookup database file
    .DESCRIPTION
        Changes the location of the database file used by all lookup commands
        and saves this configuration for future PowerShell sessions
    .PARAMETER Path
        New path for the database file
    .EXAMPLE
        Set-LookupDbPath -Path "C:\Users\MyUser\secure\mylookup.txt"
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Path
    )
    
    # Store the new path
    $Script:DbPath = $Path
    
    # Create the file if it doesn't exist
    if (-not (Test-Path -Path $Script:DbPath)) {
        New-Item -Path $Script:DbPath -ItemType File -Force | Out-Null
        Write-Output "Created new database file at $Script:DbPath"
    }
    else {
        Write-Output "Database path set to $Script:DbPath"
    }
    
    # Save the path to the configuration file for persistence across sessions
    $config = @{
        DbPath = $Script:DbPath
    }
    
    $config | ConvertTo-Json | Set-Content -Path $Script:ConfigPath -Force
    Write-Output "Path saved to configuration and will persist across PowerShell sessions."
}

function Get-LookupDbPath {
    <#
    .SYNOPSIS
        Gets the current path to the lookup database file
    .DESCRIPTION
        Returns the current database file path being used by the module
    .EXAMPLE
        Get-LookupDbPath
    #>

    [CmdletBinding()]
    param()
    
    Write-Output "Current database path: $Script:DbPath"
    
    if (Test-Path -Path $Script:DbPath) {
        Write-Output "Database file exists."
    }
    else {
        Write-Output "Warning: Database file does not exist at this location!"
    }
    
    if (Test-Path -Path $Script:ConfigPath) {
        Write-Output "Configuration file exists at: $Script:ConfigPath"
    }
    else {
        Write-Output "Configuration file does not exist yet."
    }
}

function Export-LookupData {
    <#
    .SYNOPSIS
        Exports the lookup database in a format that can be transferred to another computer
    .DESCRIPTION
        Decrypts all values and exports them to a plain text file that can be
        imported on another computer using Set-Lookup commands
    .PARAMETER Path
        Path where to save the exported file
    .PARAMETER AsCommands
        If specified, exports as PowerShell commands ready to run (recommended for security)
    .PARAMETER AsPlainText
        If specified, exports as plain text key=value pairs (less secure)
    .EXAMPLE
        Export-LookupData -Path "C:\temp\export.ps1" -AsCommands
        # Exports as runnable PowerShell commands
    .EXAMPLE
        Export-LookupData -Path "C:\temp\export.txt" -AsPlainText
        # Exports as plain text (less secure)
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Path,
        
        [Parameter(ParameterSetName = 'Commands')]
        [switch]$AsCommands,
        
        [Parameter(ParameterSetName = 'PlainText')]
        [switch]$AsPlainText
    )
    
    # Ensure database file exists
    if (-not (Test-Path -Path $Script:DbPath)) {
        Write-Error "Database file not found at $Script:DbPath"
        return
    }
    
    # Read all lines from the file
    $content = Get-Content -Path $Script:DbPath
    
    if (-not $content -or $content.Count -eq 0) {
        Write-Error "The database is empty. Nothing to export."
        return
    }
    
    # Default to AsCommands if neither is specified
    if (-not $AsCommands -and -not $AsPlainText) {
        $AsCommands = $true
    }
    
    # Process file based on export type
    if ($AsCommands) {
        # Export as PowerShell commands
        $output = @()
        $output += "# PersonalLookup export file"
        $output += "# Generated on $(Get-Date)"
        $output += "# Import by running this file or copy-pasting these commands"
        $output += ""
        
        foreach ($line in $content) {
            if ($line -match "^(.+?)=(.+?)\|(.+)$") {
                $key = $Matches[1]
                $encryptedValue = $Matches[2]
                $shortcut = $Matches[3]
                
                # Decrypt the value
                $decryptedValue = Unprotect-Value -EncryptedValue $encryptedValue
                # Escape any quotes in the value
                $escapedValue = $decryptedValue -replace '"', '`"'
                $escapedShortcut = $shortcut -replace '"', '`"'
                # Add the command to set this value with shortcut
                $output += "Set-Lookup -Key `"$key`" -Value `"$escapedValue`" -Shortcut `"$escapedShortcut`""
            }
            elseif ($line -match "^(.+?)=(.+)$") {
                $key = $Matches[1]
                $encryptedValue = $Matches[2]
                # Decrypt the value
                $decryptedValue = Unprotect-Value -EncryptedValue $encryptedValue
                # Escape any quotes in the value
                $escapedValue = $decryptedValue -replace '"', '`"'
                # Add the command to set this value
                $output += "Set-Lookup -Key `"$key`" -Value `"$escapedValue`""
            }
        }
        
        if ($PSCmdlet.ShouldProcess("PowerShell commands to $Path", "Export")) {
            $output | Set-Content -Path $Path
            Write-Output "Exported $($content.Count) items as PowerShell commands to $Path"
            Write-Output "To import on the new machine:"
            Write-Output "1. Install the PersonalLookup module"
            Write-Output "2. Run the exported script: . '$Path'"
        }
    }
    elseif ($AsPlainText) {
        # Export as plain text (less secure)
        $output = @()
        $output += "# PersonalLookup export file - PLAIN TEXT - SENSITIVE INFORMATION"
        $output += "# Generated on $(Get-Date)"
        $output += "# WARNING: This file contains decrypted values in plain text!"
        $output += "# Import using: Import-LookupData -Path '$Path' -Overwrite"
        $output += ""
        
        foreach ($line in $content) {
            if ($line -match "^(.+?)=(.+?)\|(.+)$") {
                $key = $Matches[1]
                $encryptedValue = $Matches[2]
                $shortcut = $Matches[3]
                
                # Decrypt the value
                $decryptedValue = Unprotect-Value -EncryptedValue $encryptedValue
                # Add the plain key=value|shortcut format
                $output += "$key=$decryptedValue|$shortcut"
            }
            elseif ($line -match "^(.+?)=(.+)$") {
                $key = $Matches[1]
                $encryptedValue = $Matches[2]
                
                # Decrypt the value
                $decryptedValue = Unprotect-Value -EncryptedValue $encryptedValue
                # Add the plain key=value pair
                $output += "$key=$decryptedValue"
            }
        }
        
        # Warn user about security implications
        Write-Warning "You are about to export sensitive data in PLAIN TEXT format."
        Write-Warning "This file will NOT be encrypted and could expose sensitive information."
        
        if ($PSCmdlet.ShouldProcess("plain text key-value pairs to $Path", "Export")) {
            $output | Set-Content -Path $Path
            Write-Output "Exported $($content.Count) items as plain text to $Path"
            Write-Output "To import on the new machine:"
            Write-Output "1. Install the PersonalLookup module"
            Write-Output "2. Run: Import-LookupData -Path '$Path' -Overwrite"
        }
    }
}

function Get-Need {
    <#
    .SYNOPSIS
        Retrieves or sets a lookup value
    .DESCRIPTION
        Dual-purpose function that either retrieves a value by key, or sets a value
        if both key and value parameters are provided
    .PARAMETER Key
        The key to look up or set
    .PARAMETER Value
        If provided, sets this value for the specified key
    .PARAMETER Shortcut
        Optional path to a shortcut or executable to run after copying the value
    .PARAMETER NoCopy
        If specified, doesn't copy to clipboard when retrieving
    .PARAMETER Show
        If specified, displays the value when retrieving
    .PARAMETER NoAutoClipboardClear
        If specified, doesn't automatically clear clipboard after 70 seconds
    .EXAMPLE
        Need iban
        # Retrieves IBAN value and copies to clipboard
    .EXAMPLE
        Need iban "CH132154646"
        # Sets the IBAN value
    .EXAMPLE
        Need iban "CH132154646" "C:\path\to\bank.exe"
        # Sets the IBAN value with a shortcut to the banking app
    .EXAMPLE
        Need iban -Show -NoAutoClipboardClear
        # Shows the IBAN and copies it to clipboard without auto-clearing
    #>

    [CmdletBinding(DefaultParameterSetName = 'Get')]
    [Alias("Need")]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Key,
        
        [Parameter(Mandatory = $false, Position = 1, ParameterSetName = 'Set')]
        [string]$Value,
        
        [Parameter(Mandatory = $false, Position = 2, ParameterSetName = 'Set')]
        [string]$Shortcut,
        
        [Parameter(ParameterSetName = 'Get')]
        [switch]$NoCopy,
        
        [Parameter(ParameterSetName = 'Get')]
        [switch]$Show,
        
        [Parameter(ParameterSetName = 'Get')]
        [switch]$NoAutoClipboardClear
    )
    
    # If Value is provided, we're setting a key-value pair
    if ($PSCmdlet.ParameterSetName -eq 'Set') {
        # Create the file if it doesn't exist
        if (-not (Test-Path -Path $Script:DbPath)) {
            New-Item -Path $Script:DbPath -ItemType File -Force | Out-Null
            Write-Verbose "Created new database file at $Script:DbPath"
        }
        
        # Read existing content
        $content = @()
        if (Test-Path -Path $Script:DbPath) {
            $content = Get-Content -Path $Script:DbPath
        }
        
        # Encrypt the value before storing
        $encryptedValue = Protect-Value -Value $Value
        
        # Check if key already exists
        $keyExists = $false
        $newContent = @()
        
        foreach ($line in $content) {
            if ($line -match "^$Key=") {
                # Replace existing key
                if ($Shortcut) {
                    $newContent += "$Key=$encryptedValue|$Shortcut"
                }
                else {
                    $newContent += "$Key=$encryptedValue"
                }
                $keyExists = $true
            }
            else {
                # Keep existing line
                $newContent += $line
            }
        }
        
        # Add new key if it doesn't exist
        if (-not $keyExists) {
            if ($Shortcut) {
                $newContent += "$Key=$encryptedValue|$Shortcut"
            }
            else {
                $newContent += "$Key=$encryptedValue"
            }
        }
        
        # Write back to file
        Set-Content -Path $Script:DbPath -Value $newContent
        
        if ($Shortcut) {
            Write-Output "Key '$Key' has been set successfully with shortcut: $Shortcut"
        }
        else {
            Write-Output "Key '$Key' has been set successfully."
        }

        
        # Clear the last command from history to avoid storing sensitive information
        Clear-History -Count 1

        # Ask if user wants to add another entry
        $addAnother = Read-Host "Add another entry? (y/N): "
        if ($addAnother.ToLower() -ne 'y') {
            exit
        }
    }
    else {
        # We're retrieving a value (Get parameter set)
        # Use the existing Get-Lookup function
        Get-Lookup -Key $Key -NoCopy:$NoCopy -Show:$Show -NoAutoClipboardClear:$NoAutoClipboardClear
    }
}

# Export module members
Export-ModuleMember -Function Get-Lookup, Set-Lookup, Remove-Lookup, Show-AllLookups, 
Set-LookupDbPath, Get-LookupDbPath, Export-LookupData, Get-Need -Alias dbget, dbset, dbremove, dbshow, Need