filecon 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/filecon +31 -0
- data/config.rb +91 -0
- data/config.yaml +176 -0
- data/filecon.1 +171 -0
- data/lib/filecon/version.rb +3 -0
- data/lib/filecon.rb +169 -0
- metadata +107 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: b254f6b7438d2e85fe743aacb1a2b5946b6b6ab855cb86259ed12a48b6c7e7f9
|
|
4
|
+
data.tar.gz: 7c38a7b9c191511d5684def2b6ef312e5d3aef5d37c5b38a22d82654dea96508
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 86fcec1e7a0c0d7d0a77838fc91acdfcb89d81536ea58f348de75cb881fa9e6609e685aaffc8f2d52fa8f3641b1e2af4c6b1a222828e05ca8380c4f82c9a9f61
|
|
7
|
+
data.tar.gz: 67bff21259f80836d24af248434943a59b6c6803cfb1711a59b6b4cd2cefec45a045767d2b0fbfaaa5f0476c8472535cf61f7ac3b5467e7815f2b3adc379f8bb
|
data/bin/filecon
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require "filecon"
|
|
5
|
+
rescue LoadError
|
|
6
|
+
require_relative "../lib/filecon"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
Filecon.setup_config
|
|
10
|
+
|
|
11
|
+
begin
|
|
12
|
+
config = Filecon.config
|
|
13
|
+
term = config[:term] || ENV["TERM"] || ""
|
|
14
|
+
term_hold = term + (config[:term_hold] || " --hold")
|
|
15
|
+
Typr.init( color: config[:colors][:default] )
|
|
16
|
+
Typr.clear
|
|
17
|
+
Filecon::App.new( right: -1, bottom: -1,
|
|
18
|
+
dir_history: File.read(Filecon.dir_history_path).split($/),
|
|
19
|
+
cmd_history: File.read(Filecon.cmd_history_path).split($/),
|
|
20
|
+
directory: ARGV.first, keymap: { open_file: ?o, cmd_history: ?c },
|
|
21
|
+
colors: { cmd_history: :red }.merge( config[:colors] || {} ),
|
|
22
|
+
views: config[:views] || {},
|
|
23
|
+
commands: config[:commands] || {},
|
|
24
|
+
term: term,
|
|
25
|
+
term_hold: term_hold ).fly
|
|
26
|
+
rescue => e
|
|
27
|
+
File.write File.join(Dir.tmpdir, "filecon_error.log"),
|
|
28
|
+
"#{e.class}: #{e.message}\n#{e.backtrace.first(10).join("\n")}"
|
|
29
|
+
ensure
|
|
30
|
+
Typr.exit
|
|
31
|
+
end
|
data/config.rb
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
|
|
2
|
+
term: ENV["TERM"],
|
|
3
|
+
term_hold: ENV["TERM"] + ' --hold',
|
|
4
|
+
max_history: 100,
|
|
5
|
+
|
|
6
|
+
#########################################################################
|
|
7
|
+
#
|
|
8
|
+
# COLORS
|
|
9
|
+
#
|
|
10
|
+
# standard colors: black red green yellow blue magenta cyan white grey
|
|
11
|
+
# grey shades: grey with percentage ( e.g. :grey62 for 62% grey )
|
|
12
|
+
# 8bit color: 0 - 255
|
|
13
|
+
# rgb values: [ 0-255, 0-255, 0-255 ]
|
|
14
|
+
#
|
|
15
|
+
#########################################################################
|
|
16
|
+
|
|
17
|
+
colors: {
|
|
18
|
+
types: {
|
|
19
|
+
default: [ :white, :black ],
|
|
20
|
+
image: :blue,
|
|
21
|
+
audio: :green,
|
|
22
|
+
video: :cyan,
|
|
23
|
+
directory: :yellow,
|
|
24
|
+
'x-pie-executable': :red
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
#########################################################################
|
|
29
|
+
#
|
|
30
|
+
# COMMANDS
|
|
31
|
+
#
|
|
32
|
+
# execution type:
|
|
33
|
+
#
|
|
34
|
+
# | output in status line
|
|
35
|
+
# = output in text space
|
|
36
|
+
# + run in new terminal
|
|
37
|
+
# ! ruby code evaluation
|
|
38
|
+
#
|
|
39
|
+
# substitutions:
|
|
40
|
+
#
|
|
41
|
+
# %name - selected file name
|
|
42
|
+
# %dir - pick a directory
|
|
43
|
+
# %file - pick a file
|
|
44
|
+
# %str - read string
|
|
45
|
+
#
|
|
46
|
+
########################################################################
|
|
47
|
+
|
|
48
|
+
commands: {
|
|
49
|
+
# default: { copy: 'cp %s %s' },#, move: 'mv %s %s' },
|
|
50
|
+
# default:{ list: '!Grid.new({input: %w[%name] }).pick', open: '|xdg-open',
|
|
51
|
+
default:{ open: '|xdg-open %name', diskuse: '|du -hs %name',
|
|
52
|
+
info: '=file %name', copy: '+rsync --progress %name %dir',
|
|
53
|
+
move: '|mv %name %dir', delete: '|rm %name ' },
|
|
54
|
+
directory:{ cd: '!cd %name ' },
|
|
55
|
+
text:{ view: '+less %name', edit: '+micro %name',
|
|
56
|
+
count: '|wc -l %name' },
|
|
57
|
+
troff: { manual: '+man %name' },
|
|
58
|
+
"x-ruby":{ run: '+ruby %name' },
|
|
59
|
+
html:{terminal: '+w3m %name',graphics: '|vimb %name' },
|
|
60
|
+
image:{ play: '|mpv %name' },
|
|
61
|
+
video:{ play: '|mpv %name' },
|
|
62
|
+
audio:{ play: '|mpv %name' },
|
|
63
|
+
pdf:{ view: '|mupdf %name' },
|
|
64
|
+
# epub: :pdf
|
|
65
|
+
'x-pie-executable':{ run: '|%name', run_terminal: '+%name',
|
|
66
|
+
help: '=%name --help', manual: '+man %name' }
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
#######################################################################
|
|
70
|
+
#
|
|
71
|
+
# VIEWS
|
|
72
|
+
#
|
|
73
|
+
# system infos :
|
|
74
|
+
# target permissions owner group size accessed modified created type subtype
|
|
75
|
+
#
|
|
76
|
+
######################################################################
|
|
77
|
+
|
|
78
|
+
views: {
|
|
79
|
+
# detail_ls: { ls: '|ls -l %s' },
|
|
80
|
+
# mimetypes: { type: '!type', subtype: '!subtype' },
|
|
81
|
+
# type_detail: { info: %w[ size access ], type: '|file -b %s' },
|
|
82
|
+
# type_detail:{ size: :size, type: '|file -b %name' },
|
|
83
|
+
content:{ content: '|head -n 50 %name' },
|
|
84
|
+
filetype:{ type: true, subtype: true, description: '|file -b %name' },
|
|
85
|
+
lines:{ lines: '|wc -l %name' },
|
|
86
|
+
|
|
87
|
+
# content:{ content: '!`head -n 50 %name `.gsub $/, ?|' },
|
|
88
|
+
whatis:{ whatis: #'|whatis %name' }
|
|
89
|
+
'!open(\'|whatis %name 2>&1\').read.match(/[-:]\s(.*)$/)[1] ' }
|
|
90
|
+
# "!open(\"|whatis %name 2>&1\").read.match(/[-:]\s(.*)$/)[1] " }
|
|
91
|
+
}
|
data/config.yaml
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Filecon Configuration
|
|
3
|
+
# =============================================================================
|
|
4
|
+
#
|
|
5
|
+
# This is the default configuration file for Filecon, a terminal file manager.
|
|
6
|
+
# Copy this file to ~/.config/filecon/config.yaml and customize as needed.
|
|
7
|
+
#
|
|
8
|
+
# All settings are optional. Filecon will use sensible defaults if values
|
|
9
|
+
# are not specified.
|
|
10
|
+
#
|
|
11
|
+
# =============================================================================
|
|
12
|
+
|
|
13
|
+
# Terminal settings
|
|
14
|
+
# -----------------
|
|
15
|
+
# The terminal emulator to use for Filecon's interface.
|
|
16
|
+
# Defaults to $TERM environment variable if not set.
|
|
17
|
+
# term: "kitty"
|
|
18
|
+
|
|
19
|
+
# Suffix appended to term for opening files in a new window.
|
|
20
|
+
# Example: if term is "foot", term_hold becomes "foot --hold"
|
|
21
|
+
term_hold: " --hold"
|
|
22
|
+
|
|
23
|
+
# Maximum number of history entries to retain.
|
|
24
|
+
# Older entries beyond this limit are automatically pruned.
|
|
25
|
+
max_history: 100
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# =============================================================================
|
|
29
|
+
# COLORS
|
|
30
|
+
# =============================================================================
|
|
31
|
+
#
|
|
32
|
+
# Customize the color scheme for different file types in the browser view.
|
|
33
|
+
#
|
|
34
|
+
# Color values can be:
|
|
35
|
+
# - Named colors: black, red, green, yellow, blue, magenta, cyan, white, grey
|
|
36
|
+
# - Grey shades: grey0 through grey100 (e.g., grey62 for 62% grey)
|
|
37
|
+
# - 8-bit palette: 0 - 255 (maps to terminal's 256-color palette)
|
|
38
|
+
# - RGB triplets: [0-255, 0-255, 0-255] (true color terminals)
|
|
39
|
+
#
|
|
40
|
+
# Usage:
|
|
41
|
+
# Foreground color only: "blue"
|
|
42
|
+
# Foreground + background: ["white", "black"]
|
|
43
|
+
#
|
|
44
|
+
# =============================================================================
|
|
45
|
+
|
|
46
|
+
colors:
|
|
47
|
+
default: ["white", "black"]
|
|
48
|
+
types:
|
|
49
|
+
image: "blue"
|
|
50
|
+
audio: "green"
|
|
51
|
+
video: "cyan"
|
|
52
|
+
directory: "yellow"
|
|
53
|
+
"x-pie-executable": "red"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# =============================================================================
|
|
57
|
+
# COMMANDS
|
|
58
|
+
# =============================================================================
|
|
59
|
+
#
|
|
60
|
+
# Define commands available for different file types. Each file type (MIME type
|
|
61
|
+
# category) maps to a set of named commands that can be executed on files of
|
|
62
|
+
# that type.
|
|
63
|
+
#
|
|
64
|
+
# COMMAND PREFIXES (execution type):
|
|
65
|
+
#
|
|
66
|
+
# | Pipe output to status line
|
|
67
|
+
# The command's stdout is displayed in the status bar at the bottom.
|
|
68
|
+
# Example: "|wc -l %name" shows line count in status
|
|
69
|
+
#
|
|
70
|
+
# = Display output in text area
|
|
71
|
+
# The command's output replaces the file listing with a text view.
|
|
72
|
+
# Example: "=file %name" shows file info in the text area
|
|
73
|
+
#
|
|
74
|
+
# + Run in new terminal window
|
|
75
|
+
# Opens a new terminal window to run the command.
|
|
76
|
+
# Example: "+less %name" opens a pager in a new window
|
|
77
|
+
#
|
|
78
|
+
# ! Evaluate as Ruby code
|
|
79
|
+
# The command string is evaluated as Ruby code.
|
|
80
|
+
# Example: "!cd %name" executes Ruby's cd command
|
|
81
|
+
#
|
|
82
|
+
# SUBSTITUTION VARIABLES:
|
|
83
|
+
#
|
|
84
|
+
# %name - Path(s) to selected file(s)
|
|
85
|
+
# Single file: "/path/to/file.txt"
|
|
86
|
+
# Multiple: "/path/to/file1" "/path/to/file2"
|
|
87
|
+
#
|
|
88
|
+
# %dir - Opens directory picker, inserts chosen path
|
|
89
|
+
#
|
|
90
|
+
# %file - Opens file picker, inserts chosen path
|
|
91
|
+
#
|
|
92
|
+
# %str - Prompts for text input, inserts the string
|
|
93
|
+
#
|
|
94
|
+
# =============================================================================
|
|
95
|
+
|
|
96
|
+
commands:
|
|
97
|
+
default:
|
|
98
|
+
open: "|xdg-open %name"
|
|
99
|
+
diskuse: "|du -hs %name"
|
|
100
|
+
info: "=file %name"
|
|
101
|
+
copy: "+rsync --progress %name %dir"
|
|
102
|
+
move: "|mv %name %dir"
|
|
103
|
+
delete: "|rm %name"
|
|
104
|
+
|
|
105
|
+
directory:
|
|
106
|
+
cd: "!cd %name"
|
|
107
|
+
|
|
108
|
+
text:
|
|
109
|
+
view: "+less %name"
|
|
110
|
+
edit: "+micro %name"
|
|
111
|
+
count: "|wc -l %name"
|
|
112
|
+
|
|
113
|
+
troff:
|
|
114
|
+
manual: "+man %name"
|
|
115
|
+
|
|
116
|
+
"x-ruby":
|
|
117
|
+
run: "+ruby %name"
|
|
118
|
+
|
|
119
|
+
html:
|
|
120
|
+
terminal: "+w3m %name"
|
|
121
|
+
graphics: "|vimb %name"
|
|
122
|
+
|
|
123
|
+
image:
|
|
124
|
+
play: "|mpv %name"
|
|
125
|
+
|
|
126
|
+
video:
|
|
127
|
+
play: "|mpv %name"
|
|
128
|
+
|
|
129
|
+
audio:
|
|
130
|
+
play: "|mpv %name"
|
|
131
|
+
|
|
132
|
+
pdf:
|
|
133
|
+
view: "|mupdf %name"
|
|
134
|
+
|
|
135
|
+
"x-pie-executable":
|
|
136
|
+
run: "|%name"
|
|
137
|
+
run_terminal: "+%name"
|
|
138
|
+
help: "=%name --help"
|
|
139
|
+
manual: "+man %name"
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# =============================================================================
|
|
143
|
+
# VIEWS
|
|
144
|
+
# =============================================================================
|
|
145
|
+
#
|
|
146
|
+
# Define custom column views for the file browser. Each view is a named
|
|
147
|
+
# configuration that adds computed columns to the file listing.
|
|
148
|
+
#
|
|
149
|
+
# View values can be:
|
|
150
|
+
# - true Use the built-in column for this field
|
|
151
|
+
# - A string A shell command to execute (with %name substitution)
|
|
152
|
+
# - A symbol Reference to a system field (e.g., :size, :type, :subtype)
|
|
153
|
+
#
|
|
154
|
+
# Available system fields:
|
|
155
|
+
# target, permissions, owner, group, size,
|
|
156
|
+
# accessed, modified, created, type, subtype
|
|
157
|
+
#
|
|
158
|
+
# When a view is activated, its columns are appended to the default file
|
|
159
|
+
# listing, providing additional information about each file.
|
|
160
|
+
#
|
|
161
|
+
# =============================================================================
|
|
162
|
+
|
|
163
|
+
views:
|
|
164
|
+
content:
|
|
165
|
+
content: "|head -n 50 %name"
|
|
166
|
+
|
|
167
|
+
filetype:
|
|
168
|
+
type: true
|
|
169
|
+
subtype: true
|
|
170
|
+
description: "|file -b %name"
|
|
171
|
+
|
|
172
|
+
lines:
|
|
173
|
+
lines: "|wc -l %name"
|
|
174
|
+
|
|
175
|
+
whatis:
|
|
176
|
+
whatis: "!open('|whatis %name 2>&1').read.match(/[-:]\\s(.*)$/)[1]"
|
data/filecon.1
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
.TH FILECON 1 "2026-07-26" "filecon" "User Commands"
|
|
2
|
+
.SH NAME
|
|
3
|
+
filecon \- interactive terminal file manager with speed-typing navigation
|
|
4
|
+
.SH SYNOPSIS
|
|
5
|
+
.B filecon
|
|
6
|
+
.RI [ directory ]
|
|
7
|
+
.SH DESCRIPTION
|
|
8
|
+
.B filecon
|
|
9
|
+
is a terminal-based file manager built on top of the
|
|
10
|
+
.B typerspeed
|
|
11
|
+
Ruby library. It displays directory entries in a grid with columns for name,
|
|
12
|
+
symlink target, permissions, owner, group, size, timestamps, and MIME type.
|
|
13
|
+
Directories appear first in yellow; files are colored by MIME type.
|
|
14
|
+
.PP
|
|
15
|
+
Navigation is done by typing hint characters (1\-9, 0) displayed at the
|
|
16
|
+
start of each row, enabling fast keyboard-only operation.
|
|
17
|
+
.SH OPTIONS
|
|
18
|
+
.TP
|
|
19
|
+
.I directory
|
|
20
|
+
Starting directory to browse. Defaults to the current working directory.
|
|
21
|
+
.SH NAVIGATION KEYS
|
|
22
|
+
.TP
|
|
23
|
+
.B h
|
|
24
|
+
Show help
|
|
25
|
+
.TP
|
|
26
|
+
.B r
|
|
27
|
+
Reset view (clears filters and sorts)
|
|
28
|
+
.TP
|
|
29
|
+
.B d
|
|
30
|
+
Open directory history picker
|
|
31
|
+
.TP
|
|
32
|
+
.B m / M
|
|
33
|
+
Mark row / mark range
|
|
34
|
+
.TP
|
|
35
|
+
.B a / i
|
|
36
|
+
Mark all files / invert selection
|
|
37
|
+
.TP
|
|
38
|
+
.B v
|
|
39
|
+
Switch column view
|
|
40
|
+
.TP
|
|
41
|
+
.B s
|
|
42
|
+
Sort by column
|
|
43
|
+
.TP
|
|
44
|
+
.B f
|
|
45
|
+
Filter rows
|
|
46
|
+
.TP
|
|
47
|
+
.B R
|
|
48
|
+
Recurse directory tree
|
|
49
|
+
.TP
|
|
50
|
+
.B `
|
|
51
|
+
Navigate to root directory
|
|
52
|
+
.TP
|
|
53
|
+
.B ~
|
|
54
|
+
Navigate to home directory
|
|
55
|
+
.TP
|
|
56
|
+
.B Return
|
|
57
|
+
Confirm: cd into directories or open files
|
|
58
|
+
.TP
|
|
59
|
+
.B Escape
|
|
60
|
+
Quit
|
|
61
|
+
.SH FILECON KEYS
|
|
62
|
+
.TP
|
|
63
|
+
.B o
|
|
64
|
+
Open file with configured command (prompts command picker if multiple match)
|
|
65
|
+
.TP
|
|
66
|
+
.B c
|
|
67
|
+
Browse command history
|
|
68
|
+
.SH COMMANDS
|
|
69
|
+
Commands are triggered by the [o]pen action on a file. The command executed
|
|
70
|
+
depends on the file's MIME type and subtype. If multiple commands match the
|
|
71
|
+
file type, a picker is shown.
|
|
72
|
+
.SS Command Prefixes
|
|
73
|
+
.TP
|
|
74
|
+
.B |
|
|
75
|
+
Internal execution (output piped to a viewer within the UI)
|
|
76
|
+
.TP
|
|
77
|
+
.B +
|
|
78
|
+
Terminal execution (spawns an external terminal program, e.g. mpv, nano)
|
|
79
|
+
.TP
|
|
80
|
+
.B !
|
|
81
|
+
Ruby code evaluation (result displayed in UI)
|
|
82
|
+
.SH CONFIGURATION
|
|
83
|
+
On first run, the default
|
|
84
|
+
.B config.rb
|
|
85
|
+
is copied from the installation directory to
|
|
86
|
+
.BR ~/.config/filecon/ .
|
|
87
|
+
.SS Config File Locations
|
|
88
|
+
.TP
|
|
89
|
+
.B ~/.config/filecon/config.rb
|
|
90
|
+
Main configuration (colors, commands, views, term)
|
|
91
|
+
.TP
|
|
92
|
+
.B ~/.config/filecon/dir_history
|
|
93
|
+
Directory navigation history
|
|
94
|
+
.TP
|
|
95
|
+
.B ~/.config/filecon/cmd_history
|
|
96
|
+
Command execution history
|
|
97
|
+
.SS Command Substitutions
|
|
98
|
+
.TP
|
|
99
|
+
.B %name
|
|
100
|
+
Selected file name(s), quoted and space-separated
|
|
101
|
+
.TP
|
|
102
|
+
.B %dir
|
|
103
|
+
Prompt to pick a directory
|
|
104
|
+
.TP
|
|
105
|
+
.B %file
|
|
106
|
+
Prompt to pick a file
|
|
107
|
+
.TP
|
|
108
|
+
.B %str
|
|
109
|
+
Prompt for a text string (line input)
|
|
110
|
+
.SH CONFIGURATION EXAMPLES
|
|
111
|
+
.nf
|
|
112
|
+
colors: {
|
|
113
|
+
types: {
|
|
114
|
+
directory: :yellow,
|
|
115
|
+
image: :blue,
|
|
116
|
+
video: :cyan,
|
|
117
|
+
audio: :green,
|
|
118
|
+
text: 146,
|
|
119
|
+
'x-pie-executable': :red
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
commands: {
|
|
124
|
+
default: { info: '|file %name', copy: '+rsync --progress %name %dir' },
|
|
125
|
+
text: { view: '+less %name', edit: '+nano %name' },
|
|
126
|
+
html: { terminal: '+w3m %name', graphics: '|vimb %name' },
|
|
127
|
+
image: { play: '|mpv %name' },
|
|
128
|
+
video: { play: '|mpv %name' },
|
|
129
|
+
pdf: { view: '|mupdf %name' },
|
|
130
|
+
'x-pie-executable': { run: '|%name', run_terminal: '+%name',
|
|
131
|
+
help: '+%name --help', manual: '+man %name' }
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
views: {
|
|
135
|
+
content: { content: '|head %name' },
|
|
136
|
+
whatis: { whatis: "!open('|whatis %name 2>&1').read.match(...)..." }
|
|
137
|
+
}
|
|
138
|
+
.fi
|
|
139
|
+
.SH VIEWS
|
|
140
|
+
Column views control which fields are shown for each file entry.
|
|
141
|
+
.TP
|
|
142
|
+
.B content
|
|
143
|
+
Displays first lines of file content via head(1)
|
|
144
|
+
.TP
|
|
145
|
+
.B whatis
|
|
146
|
+
Shows man page description via whatis(1)
|
|
147
|
+
.PP
|
|
148
|
+
Custom views can be defined in config.rb by adding entries to the views hash.
|
|
149
|
+
.SH ENVIRONMENT
|
|
150
|
+
.TP
|
|
151
|
+
.B TERM
|
|
152
|
+
Terminal type used for curses initialization.
|
|
153
|
+
.TP
|
|
154
|
+
.B HOME
|
|
155
|
+
Used to resolve ~ and config directory path (~/.config/filecon/).
|
|
156
|
+
.SH FILES
|
|
157
|
+
.TP
|
|
158
|
+
.I ~/.config/filecon/
|
|
159
|
+
Configuration and history directory
|
|
160
|
+
.SH SEE ALSO
|
|
161
|
+
.BR mpv (1),
|
|
162
|
+
.BR less (1),
|
|
163
|
+
.BR nano (1),
|
|
164
|
+
.BR file (1),
|
|
165
|
+
.BR rsync (1),
|
|
166
|
+
.BR whatis (1),
|
|
167
|
+
.BR typr (1)
|
|
168
|
+
.SH AUTHOR
|
|
169
|
+
Part of the Typerspeed ecosystem.
|
|
170
|
+
.SH LICENSE
|
|
171
|
+
GPL-2.0-only
|
data/lib/filecon.rb
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
require "open3"
|
|
3
|
+
require "yaml"
|
|
4
|
+
|
|
5
|
+
begin
|
|
6
|
+
require_relative "../../typr/lib/typr"
|
|
7
|
+
rescue LoadError
|
|
8
|
+
require "typr"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
require_relative "filecon/version"
|
|
12
|
+
|
|
13
|
+
module Filecon
|
|
14
|
+
PATH = File.join(ENV["HOME"], ".config/filecon/")
|
|
15
|
+
|
|
16
|
+
def self.dir_history_path
|
|
17
|
+
File.join(PATH, "dir_history")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.cmd_history_path
|
|
21
|
+
File.join(PATH, "cmd_history")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.setup_config
|
|
25
|
+
FileUtils.mkpath PATH unless File.exist? PATH
|
|
26
|
+
FileUtils.cp File.join(__dir__, "../config.yaml"), PATH unless File.exist? File.join(PATH, "config.yaml")
|
|
27
|
+
FileUtils.touch dir_history_path
|
|
28
|
+
FileUtils.touch cmd_history_path
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.deep_symbolize_keys(obj)
|
|
32
|
+
case obj
|
|
33
|
+
when Hash
|
|
34
|
+
obj.each_with_object({}) { |(k, v), h| h[k.to_sym] = deep_symbolize_keys(v) }
|
|
35
|
+
when Array
|
|
36
|
+
obj.map { |v| deep_symbolize_keys(v) }
|
|
37
|
+
else
|
|
38
|
+
obj
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.config
|
|
43
|
+
config_path = File.join(PATH, "config.yaml")
|
|
44
|
+
if File.exist?(config_path)
|
|
45
|
+
deep_symbolize_keys(YAML.safe_load(File.read(config_path), permitted_classes: [Symbol]))
|
|
46
|
+
else
|
|
47
|
+
{}
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class Filecon::App < Typr::Browser
|
|
53
|
+
include Typr
|
|
54
|
+
|
|
55
|
+
def cd dir, append=false; super
|
|
56
|
+
File.write Filecon.dir_history_path,
|
|
57
|
+
@dir_history[0..Filecon.config["max_history"]].join($/)
|
|
58
|
+
return
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def switch_to id=nil
|
|
62
|
+
return unless id
|
|
63
|
+
id = @views.keys[id] if id.is_a? Integer
|
|
64
|
+
view = @views[id]
|
|
65
|
+
return super if view.is_a? Array
|
|
66
|
+
data = @data.map.with_index{ |row, id| row + view.values.map{ |cmd|
|
|
67
|
+
run( build cmd, id ).read(width).to_s.scrub.gsub(/[\n\t]/, ?|) if
|
|
68
|
+
cmd.is_a?(String) }.compact }
|
|
69
|
+
@sequence = [ NAME ] + view.keys.map{ |head|
|
|
70
|
+
@header.index(head.to_s) || (@header += [head.to_s]; @header.count-1) }
|
|
71
|
+
clear
|
|
72
|
+
self << data
|
|
73
|
+
@current = id
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def open_file id=nil, default=false
|
|
77
|
+
return unless id ||= @selected[:rows].empty? ?
|
|
78
|
+
@user.ask( open:[self, :row] ) : @selected[:rows]
|
|
79
|
+
types = if id.is_a? Array
|
|
80
|
+
eval id.map{ |id| @data[id].values_at(SUBTYPE,TYPE).to_s }.join(?&)
|
|
81
|
+
else @data[id].values_at(SUBTYPE, TYPE)
|
|
82
|
+
end - [??] + [:default]
|
|
83
|
+
|
|
84
|
+
commands = @commands.values_at( *types.map(&:to_sym) ).map(&:to_a).flatten 1
|
|
85
|
+
cmd = if default; commands.first.last
|
|
86
|
+
else move left+1,top+1
|
|
87
|
+
if id.is_a?(Array); show "#{id.count.to_s} files: (#{
|
|
88
|
+
types.join ?, })".ljust width
|
|
89
|
+
else print id end
|
|
90
|
+
return unless cmd = Grid.new( left:1, top:3, right: -1,
|
|
91
|
+
input:commands, border: :light, format: [:min, :max],
|
|
92
|
+
borders: { top: nil }, alternate: false,
|
|
93
|
+
colors: {columns: [:green, :red] } ).pick( :row )
|
|
94
|
+
commands[ cmd ].last
|
|
95
|
+
end
|
|
96
|
+
cmd = build cmd, id
|
|
97
|
+
if cmd.start_with? ?|
|
|
98
|
+
fork { io = run( cmd, true )
|
|
99
|
+
until io.eof?
|
|
100
|
+
@user.draw io.readline.strip.scrub
|
|
101
|
+
sleep 0.1
|
|
102
|
+
end
|
|
103
|
+
}
|
|
104
|
+
else run( cmd, cmd[0..2] != '!cd' ) end
|
|
105
|
+
draw
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def build str, id
|
|
109
|
+
cmd = ""
|
|
110
|
+
while str[/\%(name|dir|file|str)/]
|
|
111
|
+
@user.draw( cmd += $` )
|
|
112
|
+
case $&
|
|
113
|
+
when '%name'; cmd += ?"+( id.is_a?( Array ) ? id.map{ |id|
|
|
114
|
+
@directory + @data[id][NAME] }.join('" "') :
|
|
115
|
+
@directory + @data[id][NAME] )+?"
|
|
116
|
+
when '%dir'; cmd += ?"+(pick :directory)+?"
|
|
117
|
+
when '%file'; cmd += ?"+(pick :file)+?"
|
|
118
|
+
when '%str'; cmd += Typr.read :line
|
|
119
|
+
end
|
|
120
|
+
str = str[($`+$&).size..-1]
|
|
121
|
+
end
|
|
122
|
+
cmd += $' || str
|
|
123
|
+
return cmd
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def run cmd=nil, store=false
|
|
127
|
+
return unless cmd
|
|
128
|
+
cmd = @cmd_history[cmd] if cmd.is_a? Integer
|
|
129
|
+
case cmd[0]
|
|
130
|
+
when ?! then io = StringIO.new eval( cmd[1..-1] ).to_s
|
|
131
|
+
when ?| then io = open( cmd + " 2>&1" )
|
|
132
|
+
when ?+ then io = open( ?| + @term +' '+ cmd[1..-1] + " 2>&1" )
|
|
133
|
+
when ?= then Text.new(top: 2, right:-1, bottom:-2, border: :light,
|
|
134
|
+
input:open( ?|+cmd[1..-1]+" 2>&1" ) ).pick :none
|
|
135
|
+
end
|
|
136
|
+
if store
|
|
137
|
+
@cmd_history.unshift cmd
|
|
138
|
+
@cmd_history.uniq!
|
|
139
|
+
File.write Filecon.cmd_history_path, @cmd_history[0..Filecon.config["max_history"]].join($/)
|
|
140
|
+
end
|
|
141
|
+
return io
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def cmd_history; run popup( { input: @cmd_history, align:[:left], left:left,
|
|
145
|
+
colors: { columns: [ @colors[:cmd_history] ] } } ).pick(:row), true
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def initialize args={}
|
|
149
|
+
super
|
|
150
|
+
@user.bindings.insert 1, "[o]pen"
|
|
151
|
+
@user.bindings.insert 7, "[c]ommands"
|
|
152
|
+
@user.draw
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def fly
|
|
156
|
+
loop do
|
|
157
|
+
draw
|
|
158
|
+
draw_hints :rows
|
|
159
|
+
key = Typr.read :key
|
|
160
|
+
@user.reset
|
|
161
|
+
case key
|
|
162
|
+
when KEY_ESCAPE; exit
|
|
163
|
+
else
|
|
164
|
+
id = send( key )
|
|
165
|
+
open_file id, true if id.is_a? Integer
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: filecon
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Kilian Reitmayr
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-07-26 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: typr
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: unicode-display_width
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '3.1'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '3.1'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rake
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
description: A terminal-based file manager with customizable views, commands, and
|
|
70
|
+
MIME-type based file operations, built on the Typr terminal UI toolkit.
|
|
71
|
+
email:
|
|
72
|
+
- reitmayr@protonmail.com
|
|
73
|
+
executables:
|
|
74
|
+
- filecon
|
|
75
|
+
extensions: []
|
|
76
|
+
extra_rdoc_files: []
|
|
77
|
+
files:
|
|
78
|
+
- bin/filecon
|
|
79
|
+
- config.rb
|
|
80
|
+
- config.yaml
|
|
81
|
+
- filecon.1
|
|
82
|
+
- lib/filecon.rb
|
|
83
|
+
- lib/filecon/version.rb
|
|
84
|
+
homepage: https://github.com/kilianh/filecon
|
|
85
|
+
licenses:
|
|
86
|
+
- GPL-2.0-only
|
|
87
|
+
metadata: {}
|
|
88
|
+
post_install_message:
|
|
89
|
+
rdoc_options: []
|
|
90
|
+
require_paths:
|
|
91
|
+
- lib
|
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '3.1'
|
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
|
+
requirements:
|
|
99
|
+
- - ">="
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '0'
|
|
102
|
+
requirements: []
|
|
103
|
+
rubygems_version: 3.3.15
|
|
104
|
+
signing_key:
|
|
105
|
+
specification_version: 4
|
|
106
|
+
summary: Terminal file manager built on Typr
|
|
107
|
+
test_files: []
|