mimeapps

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: BSD-3-Clause Imports: 7 Imported by: 0

README

mimeapps — go-freedesktop

ci Go Reference License Go Coverage

The freedesktop Association between MIME types and applications layer — the piece a file manager or an "Open With…" menu needs: given a MIME type, which application opens it by default, and what is the ordered list of candidates? Pure Go, CGO-free, building on the Wave-1 desktopentry library rather than re-parsing .desktop files.

Scope — what this adds, and what it reuses

This module does not reinvent application discovery. It stands on:

On top of those it builds the association layer:

  • the full mimeapps.list search order$XDG_CONFIG_HOME, each $XDG_CONFIG_DIRS, then the applications/ subdirectory of $XDG_DATA_HOME and each $XDG_DATA_DIRS — including the higher-priority <desktop>-mimeapps.list variants named after each entry of $XDG_CURRENT_DESKTOP (lowercased, e.g. gnome-mimeapps.list);
  • the three groups [Default Applications], [Added Associations] and [Removed Associations], with correct cross-directory precedence (a higher-priority default/added is committed and immune to a lower-priority removal; a higher-priority removal blacklists an id against lower-priority additions);
  • DefaultApp — the default resolved per the spec algorithm: the first existing, showable default across the files in priority order, falling back to the first candidate;
  • Candidates — the ordered candidate list: defaults, then added associations, then the legacy MimeType= keys, minus removed associations, each application listed once and validated to exist and be showable;
  • SetDefault / AddAssociation / RemoveAssociation — round-trippable edits to the user's mimeapps.list that preserve its groups, key order and comments.

Install

go get github.com/go-freedesktop/mimeapps

Quickstart

package main

import (
	"fmt"

	"github.com/go-freedesktop/mimeapps"
)

func main() {
	r := mimeapps.Load() // standard XDG environment + $XDG_CURRENT_DESKTOP

	// The default handler for a MIME type.
	if app, err := r.DefaultApp("text/html"); err == nil {
		fmt.Println("default:", app.Name, "→", app.Exec)
	}

	// The ordered "Open With…" menu.
	for _, app := range r.Candidates("image/png") {
		fmt.Println("candidate:", app.ID, app.Name)
	}

	// Make an application the user's default (persisted to mimeapps.list).
	_ = r.SetDefault("text/html", "org.mozilla.firefox.desktop")
}

The returned values are *desktopentry.Entry, so a launcher can go straight to ExpandExec to build the argv.

Public API

Symbol Purpose
Load() *Resolver build from the standard XDG env + $XDG_CURRENT_DESKTOP
LoadDirs(configDirs, appDirs, desktops) *Resolver injectable form (for tests / sandboxes)
(*Resolver).DefaultApp(mime) (*desktopentry.Entry, error) default handler, per the spec algorithm
(*Resolver).Candidates(mime) []*desktopentry.Entry ordered candidate list
(*Resolver).SetDefault(mime, id) error set the default (round-trippable write)
(*Resolver).AddAssociation(mime, id) error add an association
(*Resolver).RemoveAssociation(mime, id) error remove / blacklist an association
ErrNoDefault, ErrNotFound resolution / write error sentinels

id is a full desktop-file id such as firefox.desktop.

wasmdesk / wasmbox integration

This library is the resolver behind an "Open With…" action in the wasmdesk compositor:

  • DefaultApp(mime) picks the app to launch when a file is double-clicked; the returned *desktopentry.Entry feeds desktopentry.ExpandExec to produce the argv.
  • Candidates(mime) populates the right-click "Open With ▸" submenu.
  • SetDefault(mime, id) persists the user's choice from that menu's "Set as default" checkbox back to mimeapps.list.

Tests & coverage

CGO_ENABLED=0 go test ./...100% statement coverage, including every error branch, driven by fixtures under testdata/ (layered config/data dirs, a <desktop>-mimeapps.list, NoDisplay/OnlyShowIn apps, a removed association and a dangling default). CI additionally cross-builds and runs the suite on the six supported 64-bit targets (amd64/arm64 natively, riscv64/loong64/ppc64le/s390x under qemu-user).

License

BSD-3-Clause. Copyright (c) the go-freedesktop/mimeapps authors.


Note: the go-freedesktop org landing page and MkDocs site are deferred to the Wave-2 documentation sweep; this repo ships the README and .github profile for now.

Documentation

Overview

Package mimeapps implements the freedesktop.org Association between MIME types and applications specification: it reads the mimeapps.list files, applies the [Default Applications] / [Added Associations] / [Removed Associations] groups with the correct cross-directory precedence, and answers the two questions a file manager or an "Open With" menu asks — the default application for a MIME type and the ordered list of candidate applications.

It does not reinvent the .desktop parser: application discovery, the showable filter and the legacy MimeType= associations all come from github.com/go-freedesktop/desktopentry, and the XDG base directories from github.com/adrg/xdg. On top of those this package adds the association layer:

  • the full mimeapps.list search order ($XDG_CONFIG_HOME, $XDG_CONFIG_DIRS, then the applications/ subdirectory of $XDG_DATA_HOME and $XDG_DATA_DIRS), including the higher-priority <desktop>-mimeapps.list variants named after each entry of $XDG_CURRENT_DESKTOP;
  • Resolver.DefaultApp, the default application resolved per the spec algorithm (first existing, showable default across the files in priority order, falling back to the first candidate);
  • Resolver.Candidates, the ordered candidate list (defaults, then added associations, then the legacy MimeType= keys, minus removed associations);
  • Resolver.SetDefault, Resolver.AddAssociation and Resolver.RemoveAssociation, round-trippable edits to the user's mimeapps.list that preserve its groups, key order and comments.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoDefault is returned by [Resolver.DefaultApp] when no default and
	// no candidate application handles the MIME type.
	ErrNoDefault = errors.New("mimeapps: no application associated with MIME type")

	// ErrNotFound is returned by [Resolver.SetDefault] and
	// [Resolver.AddAssociation] when the given desktop-file id does not
	// resolve to an installed, showable application.
	ErrNotFound = errors.New("mimeapps: desktop-file id not found")
)

Errors returned by this package.

Functions

This section is empty.

Types

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver answers association queries against a fixed set of parsed mimeapps.list files and a fixed index of installed applications. Build one with Load (standard XDG environment) or LoadDirs (injectable, for tests). It is not safe for concurrent mutation via the writer methods.

func Load

func Load() *Resolver

Load builds a Resolver from the current process environment: the standard XDG configuration and data directories and $XDG_CURRENT_DESKTOP.

func LoadDirs

func LoadDirs(configDirs, appDirs, desktops []string) *Resolver

LoadDirs is the directory-injectable form of Load.

configDirs are the directories that hold a top-level mimeapps.list, most important first (conventionally $XDG_CONFIG_HOME then $XDG_CONFIG_DIRS). appDirs are the applications/ directories that hold both the installed *.desktop files and the data-level mimeapps.list, most important first (conventionally $XDG_DATA_HOME/applications then each $XDG_DATA_DIRS/applications). desktops is the $XDG_CURRENT_DESKTOP list; it selects the higher-priority <desktop>-mimeapps.list variants and gates the showability of candidate applications via OnlyShowIn/NotShowIn.

The user-writable mimeapps.list targeted by the writer methods is configDirs[0]/mimeapps.list; it is always represented (created in memory when the file is absent) so an edit on a fresh profile succeeds.

func (*Resolver) AddAssociation

func (r *Resolver) AddAssociation(mimeType, id string) error

AddAssociation adds id to the [Added Associations] for mimeType in the user's mimeapps.list (and clears any matching [Removed Associations] entry), then persists. It returns ErrNotFound when id is not an installed, showable application.

func (*Resolver) Candidates

func (r *Resolver) Candidates(mimeType string) []*desktopentry.Entry

Candidates returns the ordered list of applications that can open mimeType: the defaults first, then the added associations, then the legacy MimeType= associations of scanned .desktop entries, with the removed associations subtracted and each application listed once. Only installed, showable applications are returned.

Example

ExampleResolver_Candidates shows resolving the ordered "Open With" list and the default application for a MIME type from an injectable set of directories (the same entry point tests use).

package main

import (
	"fmt"

	"github.com/go-freedesktop/mimeapps"
)

func main() {
	r := mimeapps.LoadDirs(
		[]string{"testdata/config-home", "testdata/config-sys"},
		[]string{"testdata/apps-home", "testdata/apps-sys"},
		nil, // no XDG_CURRENT_DESKTOP filtering
	)

	def, _ := r.DefaultApp("image/png")
	fmt.Println("default:", def.Name)

	fmt.Print("candidates:")
	for _, e := range r.Candidates("image/png") {
		fmt.Print(" ", e.Name)
	}
	fmt.Println()
}
Output:
default: Example Viewer
candidates: Example Viewer Example Browser

func (*Resolver) DefaultApp

func (r *Resolver) DefaultApp(mimeType string) (*desktopentry.Entry, error)

DefaultApp returns the default application for mimeType. It scans the [Default Applications] group of each mimeapps.list in priority order and returns the first entry that is installed and showable; when no default resolves it falls back to the first entry of Resolver.Candidates. It returns ErrNoDefault when nothing handles the type.

func (*Resolver) RemoveAssociation

func (r *Resolver) RemoveAssociation(mimeType, id string) error

RemoveAssociation records id in the [Removed Associations] for mimeType in the user's mimeapps.list, drops it from that file's [Added Associations] and [Default Applications], then persists. Unlike the other writers it does not require id to be installed, so a stale association can be cleared.

func (*Resolver) SetDefault

func (r *Resolver) SetDefault(mimeType, id string) error

SetDefault makes id the default application for mimeType, replacing the [Default Applications] entry in the user's mimeapps.list, and persists the change. It returns ErrNotFound when id is not an installed, showable application.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL