Better "New Text Document" Script

I created a script that lets you specify filename, file extension, and the contents of the text document prior to creating it. It also handles cases in which files already exist and asks you what you'd like to do. It also strips out illegal characters from filenames.

I created this because there are many times that I want to just quickly dump a text into a .bat or .ps1 or .txt file without having to open up notepad or vs code. It's 2024, and we still haven't improved the basic "New Text Document" functionality in literally any file manager anywhere.

I recommend creating this as a "New User Command" in the "Customize" window... that way you can easily reuse this script in multiple places. For instance, I'm using it in my right-click context menu, and also as a button on one of my toolbars.

Hopefully others find this useful, and by all means, feel free to recommend improvements to this. I wouldn't mind seeing something like this be natively implemented into Directory Opus as well.

Jscript:

@disableifpath:!*:*
// Function to handle click event
function OnClick(clickData) {
  // Initialize dialog and set template
  var dlg = clickData.func.Dlg;
  dlg.template = "dialog1";
  dlg.Create(); // Dialog is not visible yet.
   
  // Set default value for file exists action
  dlg.Control("if-file-exists-combo-box").value =  0;
   
  // Run dialog and wait for user input
  var result = dlg.RunDlg();  
   
  // Check if the dialog was cancelled by the user
  if (result ==  0) {  
    DOpus.Output("Dialog was cancelled by the user.");
    return;  
  }
  
  // Get values from various control elements
  var fileName = dlg.Control("file-name-edit-ctrl").value.replace(/[/\\:*?"<>|]/g, ''); // Get Filename and remove all illegal characters
  var fileExt = dlg.Control("file-ext-edit-ctrl").value; // Get File Extension
  var content = dlg.Control("content-edit-ctrl").value; // Get Content
   
  // Initialize file system utility
  var fs = DOpus.FSUtil();
   
  // Construct full file path
  var fullPath = clickData.func.sourcetab.path + "\\" + fileName + "." + fileExt;
   
  // Get selected action for file exists
  var fileExistsActionIndex = dlg.Control("if-file-exists-combo-box").value;
  var fileExistsAction = ["Rename New", "Replace", "Ask Me"][fileExistsActionIndex];
   
  // Check if file exists and perform action based on user selection
  if (fs.Exists(fullPath)) {
    switch (fileExistsAction) {
      case "Replace":
        break;
      case "Rename New":
        fullPath = GenerateUniqueFilename(fs, fullPath, fileName, fileExt, clickData.func.sourcetab.path);
        break;
      case "Ask Me":
        var askDlg = DOpus.Dlg;
        askDlg.message = "File already exists. How would you like to proceed?";
        askDlg.buttons = "Replace|Rename New|Abort";
        var askResult = askDlg.Show();
        if (askResult ==  1) {
          // Replace was chosen, continue as normal
        } else if (askResult ==  2) {
          // Rename New was chosen
          fullPath = GenerateUniqueFilename(fs, fullPath, fileName, fileExt, clickData.func.sourcetab.path);
          break;
        } else {
          DOpus.Output("Operation cancelled by user.");
          return;
        }
        break;
      default:
        DOpus.Output("Unexpected option, cancelling operation.");
        return;
    }
  }
   
  // Create the file. If there's content, open it for writing.
  if (content) {
    var file = fs.OpenFile(fullPath, "w");
    if (file.error ==  0) {
      file.Write(content);
      file.Close();
      DOpus.Output("File created and content written successfully at " + fullPath);
    } else {
      DOpus.Output("Error creating file: " + file.error);
    }
  } else {
    // If there's no content, just create an empty file without opening it for writing.
    var file = fs.OpenFile(fullPath, "w");
    if (file.error ==  0) {
      file.Close(); // Immediately close the file, effectively creating an empty file.
      DOpus.Output("Empty file created successfully at " + fullPath);
    } else {
      DOpus.Output("Error creating empty file: " + file.error);
    }
  }
}
// Function to generate unique filename if file already exists
function GenerateUniqueFilename(fs, fullPath, fileName, fileExt, path) {
  var baseName = fileName;
  var counter =  0;
  while (fs.Exists(fullPath)) {
    counter++;
    fileName = baseName + " - Copy" + (counter >  1 ? " (" + counter + ")" : "");
    fullPath = path + "\\" + fileName + "." + fileExt;
  }
  return fullPath;
}

Resources:

<resources>
	<resource name="dialog1" type="dialog">
		<dialog dragdrop="yes" fontsize="12" height="246" lang="english" resize="yes" standard_buttons="ok,cancel" title="Create New Document" width="324">
			<control halign="left" height="8" name="static1" title="Filename:" type="static" valign="top" width="30" x="6" y="6" />
			<control halign="left" height="12" name="file-name-edit-ctrl" resize="w" type="edit" width="240" x="6" y="18" />
			<control halign="left" height="12" name="file-ext-edit-ctrl" resize="x" title="txt" type="edit" width="66" x="252" y="18" />
			<control halign="left" height="8" name="static2" resize="x" title="Extension:" type="static" valign="top" width="30" x="252" y="6" />
			<control halign="left" height="162" multiline="yes" name="content-edit-ctrl" resize="wh" type="edit" width="312" x="6" y="36" />
			<control halign="left" height="8" name="if-file-exists-static-text" resize="y" title="If File Exists:" type="static" valign="top" width="42" x="12" y="206" />
			<control height="40" name="if-file-exists-combo-box" resize="y" type="combo" width="120" x="66" y="204">
				<contents>
					<item text="Rename New" />
					<item text="Replace" />
					<item text="Ask Me" />
				</contents>
			</control>
		</dialog>
	</resource>
</resources>

7 Likes

wow! this is great, dopus is amazing. it took me several tried to get it to run, never created my own user command! Well Done!!! i like it.

i made a simple hotkey to create a new .txt doc and open it so i could could make a quick readme notes but this is another level!

eg... have a collection of blank documents and use a hotkey to copy and open them...

Copy "C:\Users\USER\User Programs USER_ my blank templates hidden readonly\readme.info.x.txt" HERE
{sourcepath}readme.info.x.txt

2 Likes

In Opus, you can simply paste (Ctrl-V) the clipboard text directly into the folder, and then rename the resultant file.

You can also have Opus prompt you for the filename when pasting text or image data into a new file (by modifying the Ctrl-V hotkey to add an “ask” argument), although IMO it’s easier to rename it after pasting, so you aren’t prompted in cases where the file is only needed temporarily and you don’t mind what the name is.

2 Likes

That's definitely fastest if you've already got text in your clipboard, but I neglected to mention that, my "Better New Text Document" script is useful if you just want to type some text quickly, and dump it to a text file without having to open a notepad or vs code.

So for instance, if you wanna make a very quick and dirty 1 line README file, my script allows you to do that faster than any other method, imo.

But also, some habits are just hard to break. It's hard to teach an old dog new tricks, and my first impulse when pasting text into a document is to reach for the "New Text Document" button in my right click context menu. My script serves as a nice drop-in replacement for that option.

And in my case, I just added it as the very top option and also included a fallback for creating text files the legacy way in case I ever run into any issues.

2 Likes

I am trying to implement this. I can put the JScript into a User Command. Where do I put the text in Resources?

I'm not in front of my pc right now but tonight I will respond with an image that shows you how (hopefully). (unless somebody else beats me to it. :slight_smile:)

1 Like

@Hurpin
Thanks!

@jinsight it took me a me a mintue to find this myself.

the Resources are pasted in the same window, one tab over from the Script Code tab

1 Like

@Hurpin Thank you, Great work!
@xavierarmand Just the help I needed.