All files / src/utils options.ts

60% Statements 57/95
100% Branches 0/0
0% Functions 0/3
60% Lines 57/95

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 951x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                   1x 1x     1x 1x 1x 1x 1x      
import * as os from 'node:os';
import * as fs from 'node:fs';
import * as path from 'node:path';
 
export interface KeymanDeveloperOptions {
  "use tab char"?: boolean;
  "link font sizes"?: boolean;
  "indent size"?: number;
  "use old debugger"?: boolean;
  "editor theme"?: string;
  "debugger break when exiting line"?: boolean;
  "debugger single step after break"?: boolean;
  "debugger show store offset"?: boolean;
  "debugger recompile with debug info"?: boolean;
  "debugger auto reset before compilng"?: boolean;
  "auto save before compiling"?: boolean;
  "osk auto save before importing"?: boolean;
  "web host port"?: number;
  "server keep alive"?: boolean;
  "server use local addresses"?: boolean;
  "server ngrok token"?: string;
  "server ngrok region"?: string;
  "server use ngrok"?: boolean;
  "server show console window"?: boolean;
  "char map disable database lookups"?: boolean;
  "char map auto lookup"?: boolean;
  "open keyboard files in source view"?: boolean;
  "display theme"?: string;
  "external editor path"?: string;
  "smtp server"?: string;
  "test email addresses"?: string;
  "web ladder length"?: number;
  "default project path"?: string;
  "automatically report errors"?: boolean;
  "automatically report usage"?: boolean;
  "toolbar visible"?: boolean;
  "active project"?: string;
  "prompt to upgrade projects"?: boolean;
};
 
type KeymanDeveloperOption = keyof KeymanDeveloperOptions;
 
// Default has no options set, and unit tests will use the defaults (won't call
// `loadOptions()`)
let options: KeymanDeveloperOptions = {};
 
// We only load the options from disk once on first use
let optionsLoaded = false;
 
export async function loadOptions(): Promise<KeymanDeveloperOptions> {
  if(optionsLoaded) {
    return options;
  }

  options = {};
  try {
    const optionsFile = path.join(os.homedir(), '.keymandeveloper', 'options.json');
    if(fs.existsSync(optionsFile)) {
      for(let i = 0; i < 5; i++) {
        try {
          const data = JSON.parse(fs.readFileSync(optionsFile, 'utf-8'));
          if(typeof data == 'object') {
            options = data;
          }
          break;
        } catch(e) {
          if(e?.code == 'EBUSY') {
            await new Promise(resolve => setTimeout(resolve, 500));
          } else {
            // give up, nothing to report here
            break;
          }
        }
      }
    }
  } catch(e) {
    // Nothing to report here, sadly -- because we cannot rely on Sentry at this
    // low level.
    options = {};
  }
  optionsLoaded = true;
  return options;
}
 
export function getOption<T extends KeymanDeveloperOption>(valueName: T, defaultValue: KeymanDeveloperOptions[T]): KeymanDeveloperOptions[T] {
  return options[valueName] ?? defaultValue;
}
 
/**
 * unit tests will clear options before running, for consistency
 */
export function clearOptions() {
  options = {};
  optionsLoaded = true;
}