22 * Copyright (C) Microsoft Corporation. All rights reserved.
33 *--------------------------------------------------------*/
44
5- import os = require( "os" ) ;
6- import path = require( "path" ) ;
7- import vscode = require( "vscode" ) ;
5+ import * as fs from "fs" ;
6+ import * as os from "os" ;
7+ import * as path from "path" ;
8+ import * as vscode from "vscode" ;
89import { LanguageClient , NotificationType , Position , Range , RequestType } from "vscode-languageclient" ;
910import { IFeature } from "../feature" ;
1011
@@ -132,7 +133,7 @@ export const CloseFileRequestType =
132133 "editor/closeFile" ) ;
133134
134135export const SaveFileRequestType =
135- new RequestType < string , EditorOperationResponse , void , void > (
136+ new RequestType < ISaveFileDetails , EditorOperationResponse , void , void > (
136137 "editor/saveFile" ) ;
137138
138139export const ShowErrorMessageRequestType =
@@ -151,6 +152,11 @@ export const SetStatusBarMessageRequestType =
151152 new RequestType < IStatusBarMessageDetails , EditorOperationResponse , void , void > (
152153 "editor/setStatusBarMessage" ) ;
153154
155+ export interface ISaveFileDetails {
156+ filePath : string ;
157+ newPath ?: string ;
158+ }
159+
154160export interface IStatusBarMessageDetails {
155161 message : string ;
156162 timeout ?: number ;
@@ -238,7 +244,7 @@ export class ExtensionCommandsFeature implements IFeature {
238244
239245 this . languageClient . onRequest (
240246 SaveFileRequestType ,
241- ( filePath ) => this . saveFile ( filePath ) ) ;
247+ ( saveFileDetails ) => this . saveFile ( saveFileDetails ) ) ;
242248
243249 this . languageClient . onRequest (
244250 ShowInformationMessageRequestType ,
@@ -382,24 +388,44 @@ export class ExtensionCommandsFeature implements IFeature {
382388 return promise ;
383389 }
384390
385- private saveFile ( filePath : string ) : Thenable < EditorOperationResponse > {
391+ private async saveFile ( saveFileDetails : ISaveFileDetails ) : Promise < EditorOperationResponse > {
386392
387- let promise : Thenable < EditorOperationResponse > ;
388- if ( this . findTextDocument ( this . normalizeFilePath ( filePath ) ) ) {
389- promise =
390- vscode . workspace . openTextDocument ( filePath )
391- . then ( ( doc ) => {
392- if ( doc . isDirty ) {
393- doc . save ( ) ;
394- }
395- } )
396- . then ( ( _ ) => EditorOperationResponse . Completed ) ;
397- } else {
398- promise = Promise . resolve ( EditorOperationResponse . Completed ) ;
393+ // If the file to save can't be found, just complete the request
394+ if ( ! this . findTextDocument ( this . normalizeFilePath ( saveFileDetails . filePath ) ) ) {
395+ return EditorOperationResponse . Completed ;
399396 }
400397
401- return promise ;
402- }
398+ // If no newFile is given, just save the current file
399+ if ( ! saveFileDetails . newPath ) {
400+ const doc = await vscode . workspace . openTextDocument ( saveFileDetails . filePath ) ;
401+ if ( doc . isDirty ) {
402+ await doc . save ( ) ;
403+ }
404+
405+ return EditorOperationResponse . Completed ;
406+ }
407+
408+ // Otherwise we want to save as a new file
409+
410+ // First turn the path we were given into an absolute path
411+ // Relative paths are interpreted as relative to the original file
412+ const newFileAbsolutePath = path . isAbsolute ( saveFileDetails . newPath ) ?
413+ saveFileDetails . newPath :
414+ path . resolve ( path . dirname ( saveFileDetails . filePath ) , saveFileDetails . newPath ) ;
415+
416+ // Retrieve the text out of the current document
417+ const oldDocument = await vscode . workspace . openTextDocument ( saveFileDetails . filePath ) ;
418+
419+ // Write it to the new document path
420+ fs . writeFileSync ( newFileAbsolutePath , oldDocument . getText ( ) ) ;
421+
422+ // Finally open the new document
423+ const newFileUri = vscode . Uri . file ( newFileAbsolutePath ) ;
424+ const newFile = await vscode . workspace . openTextDocument ( newFileUri ) ;
425+ vscode . window . showTextDocument ( newFile , { preview : true } ) ;
426+
427+ return EditorOperationResponse . Completed ;
428+ }
403429
404430 private normalizeFilePath ( filePath : string ) : string {
405431 const platform = os . platform ( ) ;
0 commit comments