commit a9537187196cd2fc97430522f01196f0a9eb9fcf
parent bfd368b6d2278d4ec79b84f9d1ab0d467e1378ff
Author: afify <hassan@afify.dev>
Date: Mon, 13 Sep 2021 20:28:46 +0300
[feat] add change owner and group
Diffstat:
M | README.md | | | 6 | +++++- |
M | config.def.h | | | 27 | ++++++++++++++++++++------- |
M | sfm.1 | | | 14 | +++++++++++++- |
M | sfm.c | | | 66 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
4 files changed, 102 insertions(+), 11 deletions(-)
diff --git a/README.md b/README.md
@@ -70,11 +70,15 @@ $ man sfm
| `p` | paste |
| `P` | move |
| `c` | rename |
+| `cw` | rename |
+| `co` | owner and group |
+| `cc` | exit change |
+| `cq` | exit change |
| `.` | toggle dotfiles |
| `v` | start visual mode |
| `/` | start filter |
| `ENTER` | find filter |
-| `ESC` | exit filter |
+| `ESC` | exit filter|change |
| `SPACE` | switch pane |
**visual mode**
diff --git a/config.def.h b/config.def.h
@@ -25,13 +25,15 @@ static const Cpair cstatus = { 243, 0 };
/* commands */
static const char *rm_cmd[] = { "rm", "-rf" }; /* delete */
static const char *cp_cmd[] = { "cp", "-r" }; /* copy */
+static const char *chown_cmd[] = { "chown", "-R" }; /* change file owner and group */
static const char *mv_cmd[] = { "mv" }; /* move */
static const char delconf[] = "yes";
-static const size_t rm_cmd_len = LEN(rm_cmd);
-static const size_t cp_cmd_len = LEN(cp_cmd);
-static const size_t mv_cmd_len = LEN(mv_cmd);
-static const size_t delconf_len = LEN(delconf);
+static const size_t rm_cmd_len = LEN(rm_cmd);
+static const size_t cp_cmd_len = LEN(cp_cmd);
+static const size_t chown_cmd_len = LEN(chown_cmd);
+static const size_t mv_cmd_len = LEN(mv_cmd);
+static const size_t delconf_len = LEN(delconf);
/* bookmarks */
static const char root[] = "/";
@@ -47,7 +49,6 @@ static const char *r2[] = { "r2", "-c", "vv" };
/* extensions*/
static const char *images[] = { "bmp", "jpg", "jpeg", "png", "gif", "xpm" };
-static const char *web[] = { "htm", "html" };
static const char *pdf[] = { "epub", "pdf" };
static const char *arts[] = { "xcf" };
static const char *obj[] = { "o", "a", "so" };
@@ -60,7 +61,6 @@ static const char *documents[] = { "odt", "doc", "docx", "xls", "xlsx", "odp",
static Rule rules[] = {
{videos, LEN(videos), mpv, LEN(mpv) },
{images, LEN(images), sxiv, LEN(sxiv) },
- {web, LEN(web), surf, LEN(surf) },
{pdf, LEN(pdf), mupdf, LEN(mupdf) },
{documents, LEN(documents), libreoffice, LEN(libreoffice) },
{arts, LEN(arts), gimp, LEN(gimp) },
@@ -93,12 +93,24 @@ static Key nkeys[] = {
{ {.ch = 'y'}, yank, {0} },
{ {.ch = 'p'}, paste, {0} },
{ {.ch = 'P'}, selmv, {0} },
- { {.ch = 'c'}, rname, {0} },
+ { {.ch = 'c'}, start_change, {0} },
{ {.key = TB_KEY_SPACE}, switch_pane, {0} },
{ {.ch = '\\'}, bkmrk, {.v = root} },
{ {.ch = '.'}, toggle_df, {0} },
};
+/* change keys */
+static Key ckeys[] = {
+ /* keyval function arg */
+ { {.ch = 'w'}, rname, {0} },
+ { {.ch = 'o'}, chngo, {0} },
+// { {.ch = 'p'}, chngp, {0} },
+// { {.ch = 'a'}, chngq, {0} },
+ { {.ch = 'q'}, exit_change, {0} },
+ { {.ch = 'c'}, exit_change, {0} },
+ { {.key = TB_KEY_ESC}, exit_change, {0} },
+};
+
/* visual keys */
static Key vkeys[] = {
/* keyval function arg */
@@ -116,6 +128,7 @@ static Key vkeys[] = {
static const size_t nkeyslen = LEN(nkeys);
static const size_t vkeyslen = LEN(vkeys);
+static const size_t ckeyslen = LEN(ckeys);
/* permissions */
static const mode_t ndir_perm = S_IRWXU;
diff --git a/sfm.1 b/sfm.1
@@ -64,8 +64,20 @@ paste
move
.TP
.B c
+start change
+.TP
+.B cw
rename
.TP
+.B co
+owner and group
+.TP
+.B cc
+exit change
+.TP
+.B cq
+exit change
+.TP
.B .
toggle dotfiles
.TP
@@ -101,7 +113,7 @@ exit visual mode
exit visual mode
.TP
.B ESC
-exit visual mode
+exit visual mode | change
.SH CUSTOMIZATION
sfm is customized by creating a custom
.IR config.h
diff --git a/sfm.c b/sfm.c
@@ -154,6 +154,8 @@ static void toggle_df(const Arg *arg);
static void start_filter(const Arg *arg);
static void start_vmode(const Arg *arg);
static void exit_vmode(const Arg *arg);
+static void start_change(const Arg *arg);
+static void exit_change(const Arg *arg);
static void selup(const Arg *arg);
static void seldwn(const Arg *arg);
static void selall(const Arg *arg);
@@ -167,6 +169,7 @@ static void init_files(void);
static void free_files(void);
static void yank(const Arg *arg);
static void rname(const Arg *arg);
+static void chngo(const Arg *arg);
static void dupl(const Arg *arg);
static void switch_pane(const Arg *arg);
static void quit(const Arg *arg);
@@ -193,6 +196,7 @@ static int *sel_indexes;
static size_t sel_len = 0;
static char **sel_files;
static int cont_vmode = 0;
+static int cont_change = 0;
static pid_t fork_pid = 0, main_pid;
#if defined(_SYS_INOTIFY_H)
#define READEVSZ 16
@@ -1077,7 +1081,8 @@ addwatch(Pane *pane)
#if defined(_SYS_INOTIFY_H)
return pane->inotify_wd = inotify_add_watch(inotify_fd, pane->dirn,
IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO | IN_CREATE |
- IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF);
+ IN_ATTRIB | IN_DELETE | IN_DELETE_SELF |
+ IN_MOVE_SELF);
#elif defined(_SYS_EVENT_H_)
pane->event_fd = open(pane->dirn, O_RDONLY);
if (pane->event_fd < 0)
@@ -1085,7 +1090,7 @@ addwatch(Pane *pane)
EV_SET(&evlist[pane->pane_id], pane->event_fd, EVFILT_VNODE,
EV_ADD | EV_CLEAR,
NOTE_DELETE | NOTE_EXTEND | NOTE_LINK | NOTE_RENAME |
- NOTE_REVOKE | NOTE_WRITE,
+ NOTE_ATTRIB | NOTE_REVOKE | NOTE_WRITE,
0, NULL);
return 0;
#endif
@@ -1216,6 +1221,35 @@ exit_vmode(const Arg *arg)
}
static void
+start_change(const Arg *arg)
+{
+ if (cpane->dirc < 1)
+ return;
+ struct tb_event fev;
+
+ cont_change = 0;
+ print_prompt("c [wopa]");
+ tb_present();
+ while (tb_poll_event(&fev) != 0) {
+ switch (fev.type) {
+ case TB_EVENT_KEY:
+ grabkeys(&fev, ckeys, ckeyslen);
+ if (cont_change == -1)
+ return;
+ tb_present();
+ break;
+ }
+ }
+}
+
+static void
+exit_change(const Arg *arg)
+{
+ cont_change = -1;
+ print_info(cpane, NULL);
+}
+
+static void
selup(const Arg *arg)
{
mv_ver(arg);
@@ -1415,6 +1449,34 @@ rname(const Arg *arg)
PERROR(spawn(rename_cmd, 3, NULL, 0, NULL, DontWait) < 0);
free(input_name);
+ exit_change(0);
+}
+
+static void
+chngo(const Arg *arg)
+{
+ if (cpane->dirc < 1)
+ return;
+ char *input_og;
+ char *tmp[1];
+
+ input_og = ecalloc(MAX_N, sizeof(char));
+
+ if (get_usrinput(input_og, MAX_N, "OWNER:GROUP %s",
+ basename(CURSOR(cpane).name)) < 0) {
+ free(input_og);
+ return;
+ }
+
+ tmp[0] = input_og;
+ if (spawn(chown_cmd, chown_cmd_len, tmp, 1, CURSOR(cpane).name,
+ DontWait) < 0) {
+ print_error(strerror(errno));
+ return;
+ }
+
+ free(input_og);
+ exit_change(0);
}
static void