1

I am trying to programmatically invoke an OS X editor from a script which:

  • does not add smart quotes or any non-ascii characters while editing
  • will work "out of the box" on any standard mac system
  • allows the user to click the mouse to position the cursor

Sadly Nano and friends do not allow cursor positioning, and Apple lost its mind with TextEdit upgrades and really destroyed that editor!

My best hope is that there is some programatic way to configure TextEdit to behave as an ASCII editor. Alternatively, is there a third party editor whose license allows that I can include with my script to serve this need?

===== USAGE CONTEXT I have a python script that runs 'out-of-the-box' on any mac. Now I want that script to invoke an editor on an ASCII file that I need stay as an ASCII file.
I don't want to require the user to do manual configuring, I want the script to initialize itself. Ideally it would not change any global environment settings, but I can give that second requirement up, if I have no choice.

  • 2
    Do you intend to distribute the script and editor commercially or publicly? Would you accept a GNU GPL licensed editor? Are you comfortable learning a little Objective-C or Mac app development? – Graham Miln May 22 '15 at 5:30
  • 1
    emacs? It has a simple mouse mode: stackoverflow.com/questions/5710334/… – Ian C. May 22 '15 at 5:33
  • Can't you just accept rich text and convert it to plain ascii in the background? – CousinCocaine May 22 '15 at 8:07
  • 3
    nano has the mouse positioning, just ⌥ ALT + Click to place the cursor . – Mateusz Szlosek May 22 '15 at 10:09
  • @GrahamMiln GPL is so draconian, I hate to do that to my project.... not really expecting commercial, but I hate the stickiness of that contract. – Dan Oblinger May 22 '15 at 18:51
5

Any texteditor & textutil

Still intrigued by your problem I found the following solution. There is a Terminal app called textutil and it allows to convert richtext to plane text.

  • Edit and save your 'Rich' text anyway you want to (like in TextEdit).
  • Use the commandline textutil to convert your rich text to normal text

    textutil richtext.rtf -convert txt
    
  • You can also pipe the textutil output through sed to replace smartquotes and do whatever your want with it

    textutil richtext.rtf -convert txt -stdout | sed s/[”“]/'"'/g
    

    rich text

Becomes:

Hello, this is rich Text with "smart" quotes

  • Thanks! this is perhaps the best of the lousy options and Apple has left me with. (this is why I feel they have lost their mind. A UNIX based OS, w/o a text editor that comes out of the box is just stupidity!) What I can do is kick off a process which busy loops waiting for the file to be updated, when it is updated, then I can run textutil to convert the file, then I need to forcably kill the editor process, so the user does not edit the file again after I have converted it. The whole thing is just gross, but I think you have landed on the best solution to needless problem Apple created – Dan Oblinger May 22 '15 at 18:44
3

TextEdit

You mention that Apple lost its mind with TextEdit. In what way specifically? Anyway, I would suggest TextEdit:

  • It can open any .txt file as plain text
  • It works out of the box
  • It allows users to use the mouse

You can list your current preferences programatically like:

defaults read com.apple.TextEdit

You can always set the preferences programatically like this:

defaults write com.apple.TextEdit RichText 0

TextEdit preferences

Keep in mind that your system settings for quotes can sometimes interfere with the smart quotes settings in TextEdit. To disable smart quotes systemwide:

  • Go to System preferences -> Keyboard
  • Go to the 'Text' tab
  • Uncheck the 'Use smart quotes and dashes' box

Disable Smart Quotes

  • I tried your solution, but it did not seem to work. I was able to set the default, and I could see that the default was set. but even after reboot if I touched 'file.txt' and then did an 'open file.txt' TextEdit would open up, but then I typed quotes, they were smart quotes, not ASCII quotes. (I can edit your response to show the exact commands and responses if that if valuable) – Dan Oblinger May 22 '15 at 7:27
  • In what way didn't it work? – CousinCocaine May 22 '15 at 7:28
  • Smart quotes are part of your preferred system settings. You have smart quotes to default. I'll update the answer. – CousinCocaine May 22 '15 at 7:39
  • As I say I am trying to "programmatically invoke an OS X editor from a script" so your answer of using "$ defaults write ..." was on the right track. I am going to clarify the use case in my question above. I have a script that runs 'out-of-the-box' on any mac. Now I want that script to invoke an editor on file that I need stay as an ASCII file. I don't want any user twiddling of the interface during setup. Best if I can not disturb the user's setting of their applications, but I can forgo this second request if I must. – Dan Oblinger May 22 '15 at 7:58
  • I understand. Good luck – CousinCocaine May 22 '15 at 8:00
1

HTML/Javascript

A way to do some simple text editing independent of the system is using a combination of HTML and Javascript. This is Ascii as simple as it gets.

The code below is shamelessly stolen from the thiscouldbebetter.wordpress.com, and will give you some direction on how to implement this.

<html>
<body>

<table>
  <tr><td>Text to Save:</td></tr>
  <tr>
    <td colspan="3">
      <textarea id="inputTextToSave" style="width:512px;height:256px"></textarea>
    </td>
  </tr>
  <tr>
    <td>Filename to Save As:</td>
    <td><input id="inputFileNameToSaveAs"></input></td>
    <td><button onclick="saveTextAsFile()">Save Text to File</button></td>
  </tr>
  <tr>
    <td>Select a File to Load:</td>
    <td><input type="file" id="fileToLoad"></td>
    <td><button onclick="loadFileAsText()">Load Selected File</button><td>
  </tr>
</table>

<script type='text/javascript'>

function saveTextAsFile()
{
  var textToWrite = document.getElementById("inputTextToSave").value;
  var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
  var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs").value;

  var downloadLink = document.createElement("a");
  downloadLink.download = fileNameToSaveAs;
  downloadLink.innerHTML = "Download File";
  if (window.webkitURL != null)
  {
    // Chrome allows the link to be clicked
    // without actually adding it to the DOM.
    downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
  }
  else
  {
    // Firefox requires the link to be added to the DOM
    // before it can be clicked.
    downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
    downloadLink.onclick = destroyClickedElement;
    downloadLink.style.display = "none";
    document.body.appendChild(downloadLink);
  }

  downloadLink.click();
}

function destroyClickedElement(event)
{
  document.body.removeChild(event.target);
}

function loadFileAsText()
{
  var fileToLoad = document.getElementById("fileToLoad").files[0];

  var fileReader = new FileReader();
  fileReader.onload = function(fileLoadedEvent) 
  {
    var textFromFileLoaded = fileLoadedEvent.target.result;
    document.getElementById("inputTextToSave").value = textFromFileLoaded;
  };
  fileReader.readAsText(fileToLoad, "UTF-8");
}

</script>

</body>
</html>
  • Hah, you answered twice, with to very different approaches. this one is certainly out of the box! It is possible I can adapt it. my challenge is I need to invoke it from a script, and tell it what file it is editing, then have it be easy for the user to save that file. Not sure if it is possible to communicate into the JS app from the outside... I don't think it has access to ARGV on the browser invocation, or the osx 'open' statement. – Dan Oblinger May 22 '15 at 8:08
  • perhaps one could have a fix file in /tmp that contained the name of the file to edit? getting pretty hacky, but perhaps that could work --- do you have other thoughts about such an adaptation. (just to be clear, what I wish is that I could do the equivelent in my code: os.system("open -a myfile.txt") and this present the user with an editor on that file – Dan Oblinger May 22 '15 at 8:10
  • It should be possible: open -a Safari file.html hardecode the txt path and embed javascript in html – CousinCocaine May 22 '15 at 8:11
1

Nano allows curser positioning. Of course, this is because Terminal itself provides this option. Simply Option+Click where you need it to go. This was previously an option you had to enable in the Terminal Preferences, but for the last few OS X versions, is enabled by default (or hardcoded). It will work in most command line programs, including other editors like vim or emacs.

Another option that's enable by default is Scroll Alternative Screen. It lets interactive screens like man or nano be scrolled instead of scrolling the terminal screen. This works with scrolling from a touchpad or a scroll wheel or a magic mouse wheel as well.

  • Not just nano, but pico, emacs and vim (all built-in) also allow cursor positioning using the mouse with option+Click. – drfrogsplat Oct 7 '15 at 2:14
  • @drfrogsplat I tried to say that, but the wording was blah. Updated. Also, pico is simply symlinked to nano since 10.3 (iirc), as is vi to vim – cde Oct 7 '15 at 2:41
  • thanks, my goal was to allow non programmers to edit a text file. I worry that each of those editors are a bit wonky to save file and exit. it is really sad that this capacity was stripped from the mac. (textedit would be the perfect editor, but I need to programmatically permanently change the configuation of the target machine--to disable smart quotes. no so cool. – Dan Oblinger Oct 7 '15 at 6:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .