From cb14a04fbedf7cbad3cc2731b0eb6c31b83a7421 Mon Sep 17 00:00:00 2001 From: Glenn Date: Fri, 24 Nov 2023 10:25:30 +0100 Subject: [PATCH] feat: add support for auto-open option (-o, --open) --- src/cli.cr | 56 ++++++++++++++++++++++-- src/config.cr | 14 +++--- src/models/abstract_filesystem_config.cr | 6 +++ src/models/concerns/base.cr | 4 +- src/models/global_config.cr | 6 ++- src/models/gocryptfs_config.cr | 2 +- src/models/httpdirfs_config.cr | 2 +- src/models/sshfs_config.cr | 2 +- 8 files changed, 77 insertions(+), 15 deletions(-) diff --git a/src/cli.cr b/src/cli.cr index 844fa91..327fc92 100644 --- a/src/cli.cr +++ b/src/cli.cr @@ -38,6 +38,11 @@ module GX @config.verbose = true end + parser.on("-o", "--open", "Automatically open directory after mount") do |flag| + Log.info { "Auto-open enabled" } + @config.auto_open = true + end + parser.on("--version", "Show version") do |flag| @config.mode = Config::Mode::ShowVersion end @@ -93,10 +98,56 @@ module GX when Config::Mode::Mount @config.load_from_file filesystem = choose_filesystem - mount_or_umount(filesystem) if !filesystem.nil? + raise Models::InvalidFilesystemError.new("Invalid filesystem") if filesystem.nil? + + mount_or_umount(filesystem) + auto_open(filesystem) if @config.auto_open end end + def auto_open(filesystem) + # FIXME: support xdg-open + # FIXME: support mailcap + # FIXME: support user-defined command + # FIXME: detect graphical environment + + mount_point_safe = filesystem.mount_point + raise Models::InvalidMountpointError.new("Invalid filesystem") if mount_point_safe.nil? + + if graphical_environment? + process = Process.new( + "xdg-open", ## FIXME: make configurable + [mount_point_safe], + input: STDIN, + output: STDOUT, + error: STDERR + ) + unless process.wait.success? + puts "Error opening filesystem".colorize(:red) + return + end + else + process = Process.new( + "vifm", ## FIXME: make configurable + [mount_point_safe], + input: STDIN, + output: STDOUT, + error: STDERR + ) + unless process.wait.success? + puts "Error opening filesystem".colorize(:red) + return + end + end + end + + def graphical_environment? + if ENV["DISPLAY"]? || ENV["WAYLAND_DISPLAY"]? + return true + end + return false + end + def choose_filesystem() names_display = {} of String => NamedTuple(filesystem: Models::AbstractFilesystemConfig, ansi_name: String) @@ -134,9 +185,6 @@ module GX end def mount_or_umount(selected_filesystem) - config_root_safe = @config.root - return if config_root_safe.nil? - if !selected_filesystem.mounted? selected_filesystem.mount() else diff --git a/src/config.cr b/src/config.cr index c936b77..9d81936 100644 --- a/src/config.cr +++ b/src/config.cr @@ -11,6 +11,9 @@ module GX class Config Log = ::Log.for("config") + class MissingFileError < Exception + end + enum Mode ConfigAdd ConfigDelete @@ -31,14 +34,15 @@ module GX property mode : Mode property path : String? property args : AddArgs.class | DelArgs.class | NoArgs.class + property auto_open : Bool def initialize() - if !ENV["HOME"]? - raise "Home directory not found" - end + raise Models::InvalidEnvironmentError.new("Home directory not found") if !ENV["HOME"]? @home_dir = ENV["HOME"] @verbose = false + @auto_open = false + @mode = Mode::Mount @filesystems = [] of Models::AbstractFilesystemConfig @path = nil @@ -66,7 +70,7 @@ module GX end Log.error { "No configuration file found in any of the standard locations" } - raise "Configuration file not found" + raise MissingFileError.new("Configuration file not found") end def load_from_file @@ -87,7 +91,7 @@ module GX root = Models::RootConfig.from_yaml(file_patched) global_mount_point = root.global.mount_point - raise "Invalid global mount point" if global_mount_point.nil? + raise Models::InvalidMountpointError.new("Invalid global mount point") if global_mount_point.nil? root.filesystems.each do |selected_filesystem| if !selected_filesystem.mount_point? diff --git a/src/models/abstract_filesystem_config.cr b/src/models/abstract_filesystem_config.cr index d1006d8..afa55bf 100644 --- a/src/models/abstract_filesystem_config.cr +++ b/src/models/abstract_filesystem_config.cr @@ -6,6 +6,12 @@ require "yaml" module GX::Models + class InvalidFilesystemError < Exception + end + + class InvalidMountpointError < Exception + end + abstract class AbstractFilesystemConfig include YAML::Serializable # include YAML::Serializable::Strict diff --git a/src/models/concerns/base.cr b/src/models/concerns/base.cr index 9f0d656..a5afda5 100644 --- a/src/models/concerns/base.cr +++ b/src/models/concerns/base.cr @@ -3,14 +3,14 @@ module GX::Models::Concerns module Base def mounted?() : Bool mount_point_safe = @mount_point - raise "Invalid mountpoint value" if mount_point_safe.nil? + raise InvalidMountpointError.new("Invalid mountpoint value") if mount_point_safe.nil? `mount`.includes?(" on #{mount_point_safe} type ") end def umount() : Nil mount_point_safe = @mount_point - raise "Invalid mountpoint value" if mount_point_safe.nil? + raise InvalidMountpointError.new("Invalid mountpoint value") if mount_point_safe.nil? system("fusermount -u #{mount_point_safe.shellescape}") fusermount_status = $? diff --git a/src/models/global_config.cr b/src/models/global_config.cr index 25759b5..91cf2b7 100644 --- a/src/models/global_config.cr +++ b/src/models/global_config.cr @@ -7,6 +7,9 @@ require "yaml" require "./abstract_filesystem_config" module GX::Models + class InvalidEnvironmentError < Exception + end + class GlobalConfig include YAML::Serializable include YAML::Serializable::Strict @@ -15,7 +18,8 @@ module GX::Models getter mount_point : String? def after_initialize() - home_dir = ENV["HOME"] || raise "Home directory not found" + raise InvalidEnvironmentError.new("Home directory not found") if !ENV["HOME"]? + home_dir = ENV["HOME"] # Set default mountpoint from global if none defined if @mount_point.nil? || @mount_point.try &.empty? diff --git a/src/models/gocryptfs_config.cr b/src/models/gocryptfs_config.cr index 2dd3cb8..5d08263 100644 --- a/src/models/gocryptfs_config.cr +++ b/src/models/gocryptfs_config.cr @@ -23,7 +23,7 @@ module GX::Models def _mount_action() mount_point_safe = @mount_point - raise "Invalid mount point" if mount_point_safe.nil? + raise InvalidMountpointError.new("Invalid mount point") if mount_point_safe.nil? process = Process.new( "gocryptfs", diff --git a/src/models/httpdirfs_config.cr b/src/models/httpdirfs_config.cr index 29ab5dd..c175558 100644 --- a/src/models/httpdirfs_config.cr +++ b/src/models/httpdirfs_config.cr @@ -23,7 +23,7 @@ module GX::Models def _mount_action() mount_point_safe = @mount_point - raise "Invalid mount point" if mount_point_safe.nil? + raise InvalidMountpointError.new("Invalid mount point") if mount_point_safe.nil? process = Process.new( "httpdirfs", diff --git a/src/models/sshfs_config.cr b/src/models/sshfs_config.cr index 6b7e35c..c7e5853 100644 --- a/src/models/sshfs_config.cr +++ b/src/models/sshfs_config.cr @@ -26,7 +26,7 @@ module GX::Models def _mount_action() mount_point_safe = @mount_point - raise "Invalid mount point" if mount_point_safe.nil? + raise InvalidMountpointError.new("Invalid mount point") if mount_point_safe.nil? process = Process.new( "sshfs",