How to Open The Default Text Editor in Linux

Opening default text editor in Bash?

The user's chosen editor should be in $EDITOR, but you must still choose a sane default.

"${EDITOR:-vi}" file.txt

How to open the default text editor in Linux?

There is no completely reliable concept of "default editor" on Linux, let alone more broadly Unix-like systems.

Traditionally, users would set the environment variable EDITOR to the path of their editor of choice. If this variable is set, I'm thinking you can be reasonably confident that they will know how to use it, even if they end up in something horrible like nano.

A slightly newer convention is to set VISUAL to the preferred "visual editor" - I guess the terminology comes from vi to contrast against line editors like ed.

${VISUAL-${EDITOR-nano}} path/to/new/file.txt

On Debianish systems, the system default editor is configurable via alternatives and available simply with the command editor.

On XDG systems, of course, you could simply

touch path/to/new/file.txt
xdg-open path/to/new/file.txt

Needless to say, this only works if you have XDG, i.e. In practice a Linux (or maybe modern *BSD) platform with an active graphical session (excludes Mac and pre-XDG graphical systems as well as of course any server environment where there is no GUI).

As an aside, if I can guess even roughly what your script does, it could probably be pared down to a fairly simple sed script. Remember, sed can do (almost) everything grep and tail can. Maybe see also Combining two sed commands - here is a quick and dirty refactoring.

cd /usr/share/applications
$(sed -n "s:^Exec=\([^%]*\)\(%.\(.*\)\)*:\1\3:p" "$(sed -n "s:^$1=::p" defaults.list | tail -1)" | tail -1) &

However, from quick googling, it looks like /usr/share/applications/defaults.list is specific to OpenDesktop environments; but it's the system-wide default default - the admin could have installed an override in a different location, and individual users probably have individual preferences on top of that. Finding and traversing this hierarchy is precisely what xdg-open does, so I'm not going to try to reimplement it in an ad-hoc script of my own, and suggest you shouldn't, either.

There is nothing about graphical environments in your question, so it's unclear whether you are actually looking for a simple editor for beginners who barely know how to click and drool in a graphical environment (in which case I'd say go with touch followed by xdg-open) or a competent programmers' editor which way or may not run in a window (maybe try VISUAL with fallback to EDITOR, and document that you use this mechanism).

Python3/Linux - Open text file in default editor and wait until done

Instead of trying to poll a PID, you can simply wait for the child process to terminate, using subprocess.Popen.wait():

Wait for child process to terminate. Set and return returncode attribute.

Additionally, getting the first part of get_commandline() is not guaranteed to be the launcher. The string returned by get_commandline() will match the Exec key spec, meaning the %u, %U, %f, and %F field codes in the returned string should be replaced with the correct values.

Here is some example code, based on your xdg-mime approach:

#!/usr/bin/env python3
import subprocess
import shlex
from gi.repository import Gio

my_file = 'test.txt'

# Get default application
app = subprocess.check_output(['xdg-mime', 'query', 'default', 'text/plain']).decode('utf-8').strip()

# Get command to run
command = Gio.DesktopAppInfo.new(app).get_commandline()

# Handle file paths with spaces by quoting the file path
my_file_quoted = "'" + my_file + "'"

# Replace field codes with the file path
# Also handle special case of the atom editor
command = command.replace('%u', my_file_quoted)\
.replace('%U', my_file_quoted)\
.replace('%f', my_file_quoted)\
.replace('%F', my_file_quoted if app != 'atom.desktop' else '--wait ' + my_file_quoted)

# Run the default application, and wait for it to terminate
process = subprocess.Popen(
shlex.split(command), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
process.wait()

# Now the exit code of the text editor process is available as process.returncode

I have a few remarks on my sample code.

Remark 1: Handling spaces in file paths

It is important the file path to be opened is wrapped in quotes, otherwise shlex.split(command) will split the filename on spaces.

Remark 2: Escaped % characters

The Exec key spec states

Literal percentage characters must be escaped as %%.

My use of replace() then could potentially replace % characters that were escaped. For simplicity, I chose to ignore this edge case.

Remark 3: atom

I assumed the desired behaviour is to always wait until the graphical editor has closed. In the case of the atom text editor, it will terminate immediately on launching the window unless the --wait option is provided. For this reason, I conditionally add the --wait option if the default editor is atom.

Remark 4: subprocess.DEVNULL

subprocess.DEVNULL is new in python 3.3. For older python versions, the following can be used instead:

with open(os.devnull, 'w') as DEVNULL:
process = subprocess.Popen(
shlex.split(command), stdout=DEVNULL, stderr=DEVNULL)

Testing

I tested my example code above on Ubuntu with the GNOME desktop environment. I tested with the following graphical text editors: gedit, mousepad, and atom.

C++ (Unix): Open a text file with the default editor

There is no official solution. Here is my recommendation for opening up a text editor:

If the filename extension is .txt, and xdg-open is avaliable on $PATH and the $DISPLAY variable is nonempty, then use xdg-open. Otherwise use /usr/bin/sensible-editor if it exists. Otherwise, use getenv("EDITOR"), getenv("VISUAL") or getenv("SELECTED_EDITOR"). If none of them are set, try nano, nano-tiny and then vi.

Linux Open default terminal text editor

If the system is properly configured, editor should do the job.

For instance, on my debian system, editor is configured to use nano.

$ update-alternatives --display editor
editor - auto mode
link currently points to /bin/nano
/bin/nano - priority 40
slave editor.1.gz: /usr/share/man/man1/nano.1.gz
/usr/bin/emacs23 - priority 0
slave editor.1.gz: /usr/share/man/man1/emacs.emacs23.1.gz
/usr/bin/vim.basic - priority 30
slave editor.1.gz: /usr/share/man/man1/vim.1.gz
slave editor.fr.1.gz: /usr/share/man/fr/man1/vim.1.gz
slave editor.it.1.gz: /usr/share/man/it/man1/vim.1.gz
slave editor.pl.1.gz: /usr/share/man/pl/man1/vim.1.gz
slave editor.ru.1.gz: /usr/share/man/ru/man1/vim.1.gz
/usr/bin/vim.tiny - priority 10
slave editor.1.gz: /usr/share/man/man1/vim.1.gz
slave editor.fr.1.gz: /usr/share/man/fr/man1/vim.1.gz
slave editor.it.1.gz: /usr/share/man/it/man1/vim.1.gz
slave editor.pl.1.gz: /usr/share/man/pl/man1/vim.1.gz
slave editor.ru.1.gz: /usr/share/man/ru/man1/vim.1.gz
Current 'best' version is '/bin/nano'.

I was expecting it to use the environnement variable EDITOR, but obviously it's not the case, at least on Debian.

How do I use Rust to open the user's default editor and get the edited content?

I could be wrong, but I think the way git commit works is that it creates a temporary file (.git/COMMIT_EDITMSG) and then as a sub-process it opens that file in the user's $EDITOR and then waits for the editor's process to exit/return. That will only happen when the user closes their editor. Which basically means that they can use the full power of their choice of editors, i.e. navigate in the file, save their changes, etc.

Thus, in Rust, you could use std::process::Command to open the user's editor, which you can get via the std::env::var. You can store the temporary file in a specific location if your application has one (like the .git directory for git or ~/.config/<your-app>/<your-file>, etc.) or you could create a temporary one inside the system's temporary directory returned to you by the std::env::temp_dir. (Alternatively you could use the excellent third party crate to directly create a temporary file only: tempfile)

Here's a working example using the above mentioned technique:

use std::{
env::{temp_dir, var},
fs::File,
io::Read,
process::Command,
};

fn main() {
let editor = var("EDITOR").unwrap();
let mut file_path = temp_dir();
file_path.push("editable");
File::create(&file_path).expect("Could not create file");

Command::new(editor)
.arg(&file_path)
.status()
.expect("Something went wrong");

let mut editable = String::new();
File::open(file_path)
.expect("Could not open file")
.read_to_string(&mut editable);

println!("File content:\n{}", editable);
}

How can I open a file with the standard text editor?

You can use the open crate. It supports Windows, OS X and Linux. To open a text-file on your C: drive, you can use

extern crate open;

fn main() {
open::that("C:\textfile.txt");
}

Subversion CLI default text editor on Linux

When you download the source directly (and build it - assuming you have the build dependencies met) you specify (or you can omit it) the default fallback editor. Normally source builds are done with something like this on Ubuntu (assume I have extracted/downloaded the subversion 1.8.10 source from here):

./configure
make
sudo make install

Notice the ./configure command above doesn't specify any options. The defaults will install to the prefix /usr/local . Prior to issuing those commands (on Ubuntu 12.04) I ran sudo apt-get build-dep subversion . I then did the commands above to build and install. I made sure that options 1-5 (In the OPs question) were not satisfied and then tried to commit a change to a repository. I got this as a response:

svn: E205007: Commit failed (details follow):
svn: E205007: Could not use external editor to fetch log message; consider setting the $SVN_EDITOR environment variable or using the --message (-m) or --file (-F) options
svn: E205007: None of the environment variables SVN_EDITOR, VISUAL or EDITOR are set, and no 'editor-cmd' run-time configuration option was found

Since I didn't remove the official Ubuntu subversion I had to run mine as /usr/local/bin/svn to make sure I was using the one I built. I could have used sudo apt-get remove subversion to remove the official one as well just to make sure.

Now if one runs these commands to rebuild the source:

make clean
./configure --with-editor=/usr/bin/editor
make
sudo make install

One should find that if options 1 to 5 are not satisfied and this version of subversion is run it should default to running whatever /usr/bin/editor points to. On Ubuntu that will depend on what alternative is being used.

So when Ubuntu does an official build where does their fallback editor come from? I went to the 12.04 source repository for subversion at this link . On the right hand side I downloaded the diff file subversion_1.6.17dfsg-3ubuntu3.4.diff.gz . I opened up the diff file Ubuntu uses and scrolling down you can find they use this set of ./configure options (flags):

confflags := \
--prefix=/usr \
--libdir=$(libdir) \
--mandir=\$${prefix}/share/man \
--with-apr=/usr \
--with-apr-util=/usr \
--with-neon=/usr \
--with-serf=/usr \
--with-berkeley-db=:::db \
--with-sasl=/usr \
--with-editor=/usr/bin/editor \
--with-ruby-sitedir=/usr/lib/ruby \
--with-swig=/usr \
--with-kwallet \
--with-gnome-keyring

The bold entry shows that they use /usr/bin/editor as their fallback.

I have built subversion 1.8.10 from source on Ubuntu 12.04 and got the expected behavior. This suggests one of these possibilities:

  • On one of the systems the options 1 through 5 is actually met.
  • One version of subversion was built with the --with-editor configure flag (either directly or indirectly). The fallback would point to whatever the --with-editor configure flag was set to.
  • On one of the systems the wrong version of subversion is being run. One possibility is that the official subversion on Ubuntu is in fact being used. If that is the case it was built to use /usr/bin/editor as a fallback.
  • On one of your systems you have an alias (or equivalent) for svn that specifies an editor. Aliases would be specified in a startup script like ~/.bashrc, ~/.bash_profile, /etc/bash.bashrc for example.


Related Topics



Leave a reply



Submit