Extending Filer context menus
It is possible to extend Filer context menu items by writing files that conform to the DES-EMA (Desktop Entry Specification - Extension for Menus and Actions). Apparently this format was never adopted as a standard, so it is documented here. The information on this page is based on draft 0.15 from November 23, 2010.
Note
Filer inherits its DES-EMA implementation from PCManFM, but may use a different format in the future.
It still needs to be verified which portions have actually been implemented in Filer, so currently this page describes functionality which may or may not be implemented in Filer. Corrections are welcome.
Changes take effect after a restart of Filer. To restart Filer:
Press Ctrl+Alt+Esc and click on the Desktop to force-quit it
Press Alt+F2 and enter
launch Filer --desktop
to start it again
Examples
An example of an action
In the following example, we define an “Open terminal here” action, which has three profiles. These profiles are thought to be able to open a suitable terminal in most situations. They are ordered, and so only the first profile whose conditions are met at runtime will be used in the Filer context menu.
[Desktop Entry]
Name=Open terminal here
Tooltip=Open a new terminal here
Icon=terminal
Profiles=on_folder; on_file; on_desktop;
[X-Action-Profile on_folder]
Name=open a terminal on the current folder or on the selected folder
MimeTypes=inode/directory;
# note that this means strictly less than 2, as the equal sign is part of the DES syntax
SelectionCount=< 2
Exec=launch QTerminal --workdir %d
[X-Action-Profile on_file]
Name=open a terminal in the folder which contains selected items
MimeTypes=all/allfiles;
Exec=launch QTerminal --workdir $(echo %D | cut -d ' ' -f 1)
[X-Action-Profile on_desktop]
Name=open a terminal of the desktop
Schemes=x-nautilus-desktop;
Exec=launch QTerminal --workdir ~/Desktop
This may be saved, e.g. as ~/.local/share/file-manager/actions/open-terminal.desktop
file.
Note that this is only an example of how an action may be defined in a .desktop
file. It has not been deeply tested, and there is most probably more efficient ways of opening a terminal somewhere…
An example of a menu
Suppose we would like to place the menu elements into a submenu. To achieve this, we create a second .desktop
file with following content:
[Desktop Entry]
Type=Menu
Name=Terminal menu
Tooltip=Terminal submenu
Icon=terminal-group
ItemsList=open-terminal;
This may be saved, e.g. as ~/.local/share/file-manager/actions/menu-terminal.desktop
file.
Desktop file
Desktop file format
This specification relies on the common syntax defined in the Desktop Entry Specification. Here is a summary of some main points:
Files are UTF-8 encoded.
All keys and values are case sensitive.
The
[Desktop Entry]
group must be the first group of the file.Boolean values must be
true
orfalse
.Strings, in strings lists, are semicolon-separated; the list itself ends with a semicolon.
Desktop file identifier
In the rest of this specification, when a desktop file needs to be identified, we are using the basename of the file, without the extension, calling this a desktop_file_id.
Desktop files search path
.desktop
files are searched for in XDG_DATA_DIRS/file-manager/actions
directories. All used _desktop_file_id_s should be unique.
Managed objects
Actions and profiles
This specification essentially defines how actions are to be described in .desktop
files in order to be displayed in the Filer context menu, and available as selectable items to be executed by the user.
An action might be defined as a group of several elements:
the displayable part: label, tooltip, icon
conditions which have to be met in order the item be actually displayed in the context menu; these conditions are checked against the current Filer selection; these might be mimetypes, scheme, etc.
the command to be executed, and its parameters.
As a user might want have the very same action execute a different command depending of the current environment at runtime, we define that an action is built on one to several profiles, where each profile is defined by:
conditions which have to be met in order the item be actually displayed in the context menu; these conditions are checked against the current Filer selection; these might be mimetypes, scheme, etc.
the command to be executed, and its parameters.
Menus
This specification also defines how these actions may be gathered and ordered in menus, and submenus, and so on.
A menu is defined by:
its displayable part: label, tooltip, icon
conditions which are to be met in order the menu, and recursively all of its subitems, be actually displayed in the Filer context menu
the ordered list of the items in the menu.
Conditions
As we are dealing with three level of objects (menus, actions, profiles), it appears that whether a condition must be defined at one of these levels is rather an arbitrary decision.
We so say that conditions may appear in any of these levels:
When a condition appears in a menu definition, the result of its evaluation recursively applies to all included items. If the condition is not met, then neither the menu nor any of its subitems will be displayed.
When a condition appears in an action definition, the result of its evaluation applies to all its profiles. If the condition is not met, then the action will not be candidate; the profiles will even not be considered.
Action definition
An action must be entirely defined in one .desktop
file. The action is identified by the desktop_file_id in which it is defined.
Only valid actions are displayed in the Filer context menu.
To be valid, an action must have a non-empty name, and at least one profile must be found valid at runtime.
As stated
An action is primarily defined in the [Desktop Entry]
group, which has following keys:
**Key** | **Description** | **Value type** | **Req ?** |
`Type` | This define this `.desktop` file as an Action definition. Defaults to `Action`. | string | no |
`Name` | The label of the action, as it should appear in the context menu. | localestring | YES |
`Tooltip` | The tooltip associated with the item in the context menu. Defaults to empty. | localestring | no |
`Icon` | The name of a themed icon, or the path to an icon. Defaults to empty. | localestring | no |
`Description` | A free description of the action, which may be used in the management UI, in a Web page, and so on. Defaults to empty. | localestring | no |
`SuggestedShortcut` | A shortcut suggested for the action.
Please note that this might be only a suggestion as the shortcut may be already reserved for another use. Implementation should not override an already existing shortcut to define this one.
The format may look like ` |
string | no |
`Enabled` | Whether the item is candidate to be displayed in the context menu. A user might define many actions or menus, and choose to only enable some of them from time to time. Defaults to `true`. | boolean | no |
`Hidden` | From [DES](http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html): `Hidden` should have been called `Deleted`. It means the user deleted (at his level) something that was present (at an upper level, e.g. in the system dirs). It's strictly equivalent to the `.desktop` file not existing at all, as far as that user is concerned. This can also be used to "uninstall" existing files (e.g. due to a renaming) - by letting make install install a file with `Hidden=true` in it. Defaults to `false`. | boolean | no |
`TargetContext` | Whether the item targets the Filer context menu. This means that the action will be candidate if defined conditions met the current selection. Defaults to `true`. | boolean | no |
`TargetLocation` | Whether the item targets a location menu, if Filer supports this. This means that the action will be candidate if defined conditions met the current location. Defaults to `false`. | boolean | no |
`TargetToolbar` | Whether the item targets the toolbar, if Filer supports this. Note that, in order to keep a nice and stable UI, the Filer may reserve toolbar actions to those only targeting the current folder. Defaults to `false`. | boolean | no |
`ToolbarLabel` | The label to be displayed in the toolbar, if it is not the same that those displayed in context menu. Defaults to `Name` value. | localestring | no |
`Profiles` |
The ordered list of the profiles attached to this action.
So, After reading, and maybe evaluation of dynamic elements, profiles identified by the It is up to the implementation to decide whether profiles found in this Another choice might also be:
|
strings list | YES |
Profile definition
Profile is identified by its profile_id, as an ASCII string.
Each profile defined in the Profiles
key, whether statically by its profile_id identifier, or as the result of an evaluated command, must be defined in a [X-Action-Profile _profile_id_]
group.
When several profiles are defined for an action, only the first valid profile whose conditions are met at runtime is selected to be made available in the context menu.
Defining several profiles let so the user have an ordered OR-ed set of conditions, i.e. have one action be available if one set of conditions is met, OR this same action, though most probably with a slightly different command, be available if another set of conditions is met, and so on.
In order to be valid, a profile must at least have an executable command.
**Key** | **Description** | **Value type** | **Req ?** |
`Name` | The name of the profile; this name is not displayed in the context menu, and should just be thought as a convenience for the management UI. It may also be seen as a good place for a description of what the profile exactly does. Defaults to empty. | localestring | no |
`Exec` | From [DES](http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html): command to execute, possibly with arguments | string | YES |
`Path` | The working directory the program should be started in. Defaults to base directory of the current selection, which happens to be the value of `%d` parameter. | string | no |
`ExecutionMode` | Execution mode of the program.
This may be chosen between following values:
Defaults to |
string | no |
`StartupNotify` | From [DES](http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html): if `true`, it is KNOWN that the application will send a "remove" message when started with the DESKTOP_STARTUP_ID environment variable set. If `false`, it is KNOWN that the application does not work with startup notification at all (does not shown any window, breaks even when using StartupWMClass, etc.). If absent, a reasonable handling is up to implementations (assuming false, using StartupWMClass, etc.). (See the [Startup Notification Protocol Specification](http://www.freedesktop.org/Standards/startup-notification-spec) for more details). Only relevant when `ExecutionMode=Normal`. Defaults to `false`. | boolean | no |
`StartupWMClass` | From [DES](http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html): if specified, it is known that the application will map at least one window with the given string as its WM class or WM name hint (see the [Startup Notification Protocol Specification](http://www.freedesktop.org/Standards/startup-notification-spec) for more details). Only relevant when `ExecutionMode=Normal`. Defaults to empty. | string | no |
`ExecuteAs` | The user the command must be ran as. The user may be identified by its numeric UID or by its login. The implementation should ignore a profile defining a non-existing UID or login as a value for the `ExecuteAs` key. The implementation might require the presence of a well-configured subsystem (e.g. sudo). Defaults to empty: the command will be executed as the current user. | string | no |
Menu definition
Just as an action, a menu has label, tooltip, icon.
But, where an action is intended to eventually execute a command, a menu is just a way of gathering some subitems, actions or menus, in an ordered list.
In order to be valid, a menu must have a non-empty name, and include at least one valid subitem.
It is the responsibility of the implementation to ensure that the displayed menus are relevant, i.e. not empty, with no separator at the begin or the end of the menu, with no double separator, etc.
As stated
The menu is so defined as a particular case of a .desktop
file, identified by its desktop_file_id
, whose the [Desktop Entry]
section has following keys:
**Key** | **Description** | **Value type** | **Req ?** |
`Type` | This define this `.desktop` file as a Menu definition. Must be equal to `Menu`. | string | YES |
`Name` | The label of the menu, as it should appear in the context menu. | localestring | YES |
`Tooltip` | The tooltip associated with the submenu in the context menu. Defaults to empty. | localestring | no |
`Icon` | The name of a themed icon, or the path to an icon, to be associated to the submenu. Defaults to empty. | localestring | no |
`Description` | A free description of the menu, which may be used in the management UI, in a Web page, and so on. Defaults to empty. | localestring | no |
`SuggestedShortcut` | A shortcut suggested for the menu.
Please note that this might be only a suggestion as the shortcut may be already reserved for another use. Implementation should not override an already existing shortcut to define this one.
The format may look like ` |
string | no |
`Enabled` | Whether the item is candidate to be displayed in the context menu. A user might define many actions or menus, and choose to only enable some of them from time to time. Defaults to `true`. | boolean | no |
`Hidden` | From [DES](http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html): `Hidden` should have been called `Deleted`. It means the user deleted (at his level) something that was present (at an upper level, e.g. in the system dirs). It's strictly equivalent to the `.desktop` file not existing at all, as far as that user is concerned. This can also be used to "uninstall" existing files (e.g. due to a renaming) - by letting make install install a file with `Hidden=true` in it. Defaults to `false`. | boolean | no |
`ItemsList` |
The ordered list of the subitems (actions or menus) attached to this menu.
So, The keyword Actions or menus identified here as a subitem of a menu should not be redisplayed elsewhere. Actions or menus not identified here, or not identified as subitems of a menu or of a submenu, should not be ignored by the implementation; instead of that, the implementation should display these “orphan” items, most probably at the level zero of the hierarchy (though in a unspecified order). |
strings list | YES |
Conditions
As a remainder of that has been said above, each one of the following conditions may appear in a menu, an action or a profile.
Conditions are AND-ed, that is all specified conditions which appear in a menu, an action or a profile must be met in order the item be considered as a candidate.
When a condition is defined as a string list, elements of the list are considered as OR-ed (but for When an element of the string list is negated, it must be considered as an AND condition.
Example:
The line “
MimeTypes = image/*; video/*;
” must be read as “condition is met if each file in the current selection has a mimetype ofimage/*
or ofvideo/*
”And the line “
MimeTypes = image/*; video/*; !image/bmp
” must be read as “condition is met if each file in the current selection has a mimetype ofimage/*
or ofvideo/*
, but must not have theimage/bmp
mimetype”.
**Key** | **Description** | **Value type** | **Req ?** | |||
`OnlyShowIn`, `NotShowIn` | From [DES](http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html): a list of strings identifying the environments that should display/not display a given desktop entry. Only one of these keys, either `OnlyShowIn` or `NotShowIn`, may appear in a group (for possible values see the [Desktop Menu Specification](http://www.freedesktop.org/Standards/menu-spec)). Defaults to show anywhere. | strings list | no | |||
`TryExec` | From [DES](http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html): path to an executable file on disk used to determine if some program is actually installed. If the path is not an absolute path, the file is looked up in the $PATH environment variable. If the file is not found or is not executable, this condition evals to `false`. Defaults to successful. | string | no | |||
`ShowIfRegistered` | The well-known name of a DBus service.
The item will be candidate if the named service is registered on session DBus at runtime.
Defaults to successful.
|
string | no | |||
`ShowIfTrue` | A command which, when executed, should output a string on stdout.
The item will be candidate if the outputted string is equal to `true`.
Example: `[ -r %d/.svn/entries ] && echo \"true\`
Defaults to successful.
|
string | no | |||
`ShowIfRunning` | The name of a process. The item will be candidate if the process name is found in memory at runtime. Defaults to successful. | string | no | |||
`MimeTypes` | From [DES](http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html): the MIME type(s) supported by this application.
Each mimetype may be fully specified (e.g. `audio/mpeg;`), or as a group (e.g. `image/*;`).
Mimetypes may be negated (e.g. `audio/*; !audio/mpeg;`).
Some of well-known mimetypes include:
Defaults to
|
strings list | no | |||
`Basenames` | List of basenames the selection should match in order this profile be selected. `*` character is accepted as a wildcard. Basenames may be negated (e.g. `*; !*.h;`). Defaults to `*;`. | strings list | no | |||
`Matchcase` | Whether the above `Basenames` is case sensitive. Defaults to `true`. | boolean | no | |||
`SelectionCount` | Whether this profile may be selected depending of the count of the selection. This is a string of the form `{'<'|'='|'>'} number`. Examples of valid strings are: `=0`, `> 1`, `< 10`. Defaults to `>0`. | string | no | |||
`Schemes` | The list of schemes the selection must satisfy in order the item be selected.
Examples of well-known schemes are:
Schemes may be negated, e.g.
|
strings list | no | |||
`Folders` | A list of paths the current base directory must be in in order the item be selected. A folder path may be negated (e.g. `/data; !/data/resources/secret;`). `*` character is accepted as a wildcard, replacing any level(s) of subdirectory (e.g. `/music; /video; !*/secret;`). Also note that a terminating `/*` is always implied by the definition of this key. Last, note that different implementations today widely consider that, for a directory point of view, having no selection is roughly the same that selecting the currently opened folder. If this makes a difference for your action, then | strings list | no | |||
`Capabilities` | A list of capabilities each item of the selection must satisfy in order the item be candidate.
Capabilities may be negated.
Please note that each element of the specified list must be considered as ANDed, i.e. if we have `Capabilities=Readable;Writable;!Local`, then each element of the selection must be both readable AND writable AND not local.
Capabilities have to be chosen between following predefined ones:
Defaults to an empty list (do not care of capabilities).
|
strings list | no |
Parameters
Parameters expansion
Whenever parameters are said to be accepted, they will be replaced at run-time.
It should be noted by the implementation that items, actions or menus, which were considered valid at load time, may become invalid after parameters expansion, due, for example, to a label becoming empty.
Also, this specification doesn’t make any assumption about whether a parameter is relevant in a given situation, or secure, or may be used several times, or so. It instead considers that this sort of check is up to the action creator.
The implementation should take care of correctly shell-escape the substituted values, so that it should not be needed for the action creator to use any sort of quotes to handle spaces in filenames.
Multiple execution
The action creator may want its command be executed once, giving it the list of selected items as argument.
Or the action creator may want its command be repeated for each selected item, giving to each execution a different item as argument.
Actually, the command defined in the Exec
key will be executed once, or repeated for each selected item, depending of the form of arguments.
Though some parameters are not sensible to the count of the selection (e.g. %c
, the selection count itself), most have two declensions:
a “singular” one, e.g.
%b
, the basename of the selected itema “plural” one, e.g.
%B
, a space-separated list of the basenames of selected items
When the selection is empty or contains only one element, and from this topic point of view, these two forms are exactly equivalent.
When the selection contains more than one item:
if the first relevant parameter found in the
Exec
key is of a singular form, then the implementation should consider that the command is only able to deal with one item at a time, and thus that it has to be ran one time for each selected item;contrarily, if the first relevant parameter found is of the plural form, then the implementation should consider that the command is able to deal with a list of items, and thus the command should be executed only once;
if all found parameters are “irrelevant”, then the default is to consider that the command should be executed only once.
Example:
Say the current folder is /data, and the current selection contains the three files
pierre
,paul
andjacques
.If the
Exec
key isecho %b
, then the following commands will be run:
echo pierre
echo paul
echo jacques
If the
Exec
key isecho %B
, then the following command will be run:
echo pierre paul jacques
If the
Exec
key isecho %b %B
, then the following commands will be run:
echo pierre pierre paul jacques
echo paul pierre paul jacques
echo jacques pierre paul jacques
If the
Exec
key isecho %B %b
, then the following commands will be run:
echo pierre paul jacques pierre
The basename used is the one of the first item of the selected items list as provided by the Filer. There is only a small chance that it would be those of the first visually selected item, and there is contrarily great chances that it would not be predictable at all.Even if the chosen parameter is the same for all selected items, the behavior is identical.
If theExec
key isecho %d %B
, then the following commands will be run:
echo /data pierre paul jacques
echo /data pierre paul jacques
echo /data pierre paul jacques
which obviously doesn’t make many sense.As the last three examples show up, action creator should avoid to mix singular and plural forms, unless they know what they are doing, whether it doesn’t make sense or this may lead to unwaited results.
Nonetheless, mixing singular and plural forms, though we warn against, is not an error. As a counter example, there may be some situations where a command-line of the form
echo %B %d
would be useful. In that case, the following command would be run:
echo pierre paul jacques /data
It is left as an exercise for the reader to find a use case.
The word “first” in the following table makes so reference to the case where the singular form parameter is used in a plural form command. We recall one more time that which is the “first” element is not specified, and, most probably, rather unpredictable.
**Parameter** | **Description** | **Said form** | ||
%b | (first) basename | singular | ||
%B | space-separated list of basenames | plural | ||
%c | count of selected items | irrelevant | ||
%d | (first) base directory | singular | ||
%D | space-separated list of base directory of each selected items | plural | ||
%f | (first) file name | singular | ||
%F | space-separated list of selected file names | plural | ||
%h | hostname of the (first) URI | irrelevant | ||
%m | mimetype of the (first) selected item | singular | ||
%M | space-separated list of the mimetypes of the selected items | plural | ||
%n | username of the (first) URI | irrelevant | ||
%o | no-op operator which forces a singular form of execution when specified as first parameter, ignored else | singular | ||
%O | no-op operator which forces a plural form of execution when specified as first parameter, ignored else | plural | ||
%p | port number of the (first) URI | irrelevant | ||
%s | scheme of the (first) URI | irrelevant | ||
%u | (first) URI | singular | ||
%U | space-separated list of selected URIs | plural | ||
%w | (first) basename without the extension | singular | ||
%W | space-separated list of basenames without their extension | plural | ||
%x | (first) extension | singular | ||
%X | space-separated list of extensions | plural | ||
%% | the "%" character | irrelevant |
Building the whole hierarchy
The processus described here is only a sort of meta-algorithm, whose only goal is to better specify how the menus and actions should be laid out in the final hierarchy.
The implementer might take advantage of preparing once the whole hierarchy of the menus and actions:
to minimize the time spent in the parsing of all files;
to identify and eliminate duplicate _desktop_file_id_s,
to eliminate invalid menus and actions.
as described in desktop_file_ids and invalid
.desktop
files; implementation so obtains a flat list of menus or actions;recursively build the hierarchy; this merely consists in the build of the hierarchy as a tree of menus and actions, where each desktop_file_id addressed as the subitem of a menu consumes this same id from the flat list
if the level-zero order (which is not specified here, but see desktop_file_id addressed in the level zero consumes this same id from the flat list;
else, if might be reasonable to start with an empty tree;
at the end, implementation stays with:
the output tree with some menus at the root;
some actions, left in the input flat list because they were not addressed by any menu; these left actions should be added to the level zero of the hierarchy (though in a unspecified order)
some menus, left in the input flat list because their subitems were not found; as these menus happen to be empty, they must be considered as invalid.
After this built phase, the resultant tree only contains valid (before runtime parameters expansion) menus and actions.
So, menus or actions may appear at the level zero of the whole hierarchy for only two reasons:
because they are explicitly addressed by the level-zero configuration, if the implementation defines it; this may concern menus and actions;
because these items were not addressed by any menu (but this may only concern actions).
The level-zero case
Though not strictly an action or a menu definition, the level-zero issue might be easily solved by this specification. The implementation is free to implement it or not.
Ordering the elements which have to be displayed at the level-zero of the Filer context menu is just a particular case of a menu definition.
An implementation might define a level-zero.directory
file, which would contain the ordered list of level zero items identified by their desktop_file_id
.
The [Desktop Entry]
section of this level-zero.directory
file would so have only one of the following keys:
**Key** | **Description** | **Value type** | **Req ?** |
`ItemsList` | Same signification as | strings list | no |
The level-zero.directory
file may be searched for in XDG_DATA_DIRS/file-manager/actions
. The first one found would be used.
Not finding a level-zero.directory
file should not prevent actions or menus to be displayed. Instead, they just would be displayed in an unspecified, implementation-dependent, order.
The name level-zero.directory
is chosen to not risk any collision with regular .desktop
files.
References
Contributors
Jonas Bähr
David Faure
Ted Gould
Hong Jen Yee “PCMan”
Michael Pyne
Liam R. E. Quin
Pierre Wieser