UNPKG

alm

Version:

The best IDE for TypeScript

169 lines (153 loc) 5.75 kB
/** * All our interaction with the file system generally goes through here */ import { FileModel } from "./fileModel"; import { TypedEvent } from "../../common/events"; import * as fsu from "../utils/fsu"; import * as types from "../../common/types"; import * as chalk from 'chalk'; export const savedFileChangedOnDisk = new TypedEvent<{ filePath: string; contents: string }>(); export const didEdits = new TypedEvent<{ filePath: string; edits: CodeEdit[] }>(); export const didStatusChange = new TypedEvent<types.FileStatus>(); export const editorOptionsChanged = new TypedEvent<{ filePath: string; editorOptions: types.EditorOptions }>(); export const didOpenFile = new TypedEvent<{ filePath: string, contents: string }>(); let openFiles: FileModel[] = []; export function getOpenFile(filePath: string) { if (openFiles.some(f => f.config.filePath == filePath)) { return openFiles.filter(f => f.config.filePath == filePath)[0]; } } export function getOrCreateOpenFile(filePath: string, autoCreate = false) { filePath = fsu.consistentPath(filePath); var file = getOpenFile(filePath); if (!file) { /** If you request a file that isn't there ... we are going to create it */ if (!fsu.existsSync(filePath) && autoCreate) { fsu.writeFile(filePath, ''); } file = new FileModel({ filePath: filePath }); didOpenFile.emit({ filePath, contents: file.getContents() }); file.onSavedFileChangedOnDisk.on((evt) => { savedFileChangedOnDisk.emit({ filePath, contents: evt.contents }); }); file.didEdits.on((evt) => { didEdits.emit({ filePath, edits: evt.codeEdits }); }); file.didStatusChange.on((evt) => { didStatusChange.emit({ filePath, saved: evt.saved, eol: evt.eol }); }); file.editorOptionsChanged.on((editorOptions) => { editorOptionsChanged.emit({ filePath, editorOptions }); }); openFiles.push(file); } return file; } export function closeOpenFile(filePath: string) { var file = getOpenFile(filePath); if (file) { file.save(); // Right now we still keep the file open indefinitely // openFiles = openFiles.filter(f=> f.config.filePath !== filePath); } } export function getOpenFiles(): FileModel[] { return openFiles; } export function isFileOpen(filePath: string) { return !!getOpenFile(filePath); } export function saveOpenFile(filePath: string) { let file = getOpenFile(filePath); file.save(); } /** * Editor Config Stuff */ export function watchedEditorConfigChanged() { getOpenFiles().forEach(fm => fm.recheckEditorOptions()); // TODO: // Recheck editor config for all open files :-/ // The files should emit '`editorConfigChanged`' individually // We should be listening to these events and pushing them out // The front end editor should be listening to this event by filePath too. } /** * File Tree managment functions */ import * as mkdirp from "mkdirp"; export function addFolder(filePath: string) { mkdirp.sync(filePath); } export function deleteFromDisk(data: { files: string[], dirs: string[] }) { data.files.forEach(filePath => { var file = getOpenFile(filePath); if (file) { file.delete(); openFiles = openFiles.filter(f => f.config.filePath !== filePath); } else { fsu.deleteFile(filePath); } }); data.dirs.forEach(dirPath => { // delete any open files let toClose = (filePath: string) => { return filePath.startsWith(dirPath); } openFiles.filter(f => toClose(f.config.filePath)).forEach(f => f.delete()); openFiles = openFiles.filter(f => !toClose(f.config.filePath)); // delete the dir fsu.deleteDir(dirPath); }); } export function duplicateFile(data: { src: string, dest: string }) { let contents = fsu.readFile(data.src); fsu.writeFile(data.dest, contents); } import { ncp } from "ncp"; export function duplicateDir(data: { src: string, dest: string }) { return new Promise<string>((resolve) => { ncp(data.src, data.dest, (err) => { if (err) console.log('Move failed', err); resolve(JSON.stringify(err)); }); }); } import * as mv from "mv"; export function movePath(data: { src: string, dest: string }): Promise<string> { return new Promise<string>((resolve) => { mv(data.src, data.dest, { mkdirp: true, clobber: true }, (err) => { if (err) console.log('Move failed', err); resolve(JSON.stringify(err)); }); }); } import * as open from "open"; export function launchDirectory(data: { filePath: string }): Promise<{ error?: Error }> { return new Promise<{ error?: Error }>((resolve) => { open(data.filePath); resolve({ error: null }) }); } import * as cp from 'child_process'; export function launchTerminal(data: { filePath: string }): Promise<{ error?: Error }> { return new Promise<{ error?: Error }>((resolve) => { if (process.platform === 'darwin') { cp.execSync(`osascript -e 'tell application "Terminal" to activate' -e 'tell application "Terminal" to do script "cd ${data.filePath}"'`); } else if (process.platform === 'win32') { cp.execSync(`start cmd.exe /K "cd ${data.filePath}"`); } else { // http://stackoverflow.com/a/31737949/390330 console.error(chalk.red("We don't have a command for your OS. Would love for you to help us")); } resolve({ error: null }) }); }