]> Sergey Matveev's repositories - nnn.git/commitdiff
Get nnn compile and run on Haiku (#403)
authorAnna Arad <4895022+annagrram@users.noreply.github.com>
Fri, 27 Dec 2019 18:02:20 +0000 (19:02 +0100)
committerMischievous Meerkat <engineerarun@gmail.com>
Fri, 27 Dec 2019 18:02:20 +0000 (23:32 +0530)
* Add support for Haiku OS

* Adjust DISTFILES and dist rule in haiku

Makefile
VERSION.mk [new file with mode: 0644]
misc/haiku/Makefile [new file with mode: 0644]
misc/haiku/haiku_interop.h [new file with mode: 0644]
misc/haiku/nm.cpp [new file with mode: 0644]
misc/haiku/nnn-master.recipe [new file with mode: 0644]
src/nnn.c

index 51dee9768b4399101f13d167aa3d785d62103f97..6afeec22a1426da28b7582a8a68cfc15c79fcfa4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION = 2.8.1
+include VERSION.mk
 
 PREFIX ?= /usr/local
 MANPREFIX ?= $(PREFIX)/share/man
@@ -57,7 +57,7 @@ CFLAGS += $(CFLAGS_CURSES)
 
 LDLIBS += $(LDLIBS_CURSES)
 
-DISTFILES = src nnn.1 Makefile README.md LICENSE
+DISTFILES = src nnn.1 Makefile README.md LICENSE VERSION.mk
 SRC = src/nnn.c
 HEADERS = src/nnn.h
 BIN = nnn
diff --git a/VERSION.mk b/VERSION.mk
new file mode 100644 (file)
index 0000000..b387df4
--- /dev/null
@@ -0,0 +1 @@
+VERSION = 2.8.1
diff --git a/misc/haiku/Makefile b/misc/haiku/Makefile
new file mode 100644 (file)
index 0000000..6fd576d
--- /dev/null
@@ -0,0 +1,117 @@
+include VERSION.mk
+
+PREFIX ?= /boot/system/non-packaged
+MANPREFIX ?= /boot/system/non-packaged/documentation/man
+STRIP ?= strip
+PKG_CONFIG ?= pkg-config
+INSTALL ?= install
+CP ?= cp
+
+CFLAGS_OPTIMIZATION ?= -O3
+
+O_DEBUG := 0
+O_NORL := 0  # no readline support
+O_NOLOC := 0  # no locale support
+
+# convert targets to flags for backwards compatibility
+ifneq ($(filter debug,$(MAKECMDGOALS)),)
+       O_DEBUG := 1
+endif
+ifneq ($(filter norl,$(MAKECMDGOALS)),)
+       O_NORL := 1
+endif
+ifneq ($(filter noloc,$(MAKECMDGOALS)),)
+       O_NORL := 1
+       O_NOLOC := 1
+endif
+
+ifeq ($(O_DEBUG),1)
+       CPPFLAGS += -DDBGMODE
+       CFLAGS += -g
+       LDLIBS += -lrt
+endif
+
+ifeq ($(O_NORL),1)
+       CPPFLAGS += -DNORL
+else
+       LDLIBS += -lreadline
+endif
+
+ifeq ($(O_NOLOC),1)
+       CPPFLAGS += -DNOLOCALE
+endif
+
+ifeq ($(shell $(PKG_CONFIG) ncursesw && echo 1),1)
+       CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncursesw)
+       LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs   ncursesw)
+else ifeq ($(shell $(PKG_CONFIG) ncurses && echo 1),1)
+       CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncurses)
+       LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs   ncurses)
+else
+       LDLIBS_CURSES ?= -lncurses
+endif
+
+ifeq ($(shell uname -s), Haiku)
+       LDLIBS_HAIKU ?= -lstdc++ -lbe
+       SRC_HAIKU ?= misc/haiku/nm.cpp
+       OBJS_HAIKU ?= misc/haiku/nm.o
+endif
+
+CFLAGS += -Wall -Wextra
+CFLAGS += $(CFLAGS_OPTIMIZATION)
+CFLAGS += $(CFLAGS_CURSES)
+
+LDLIBS += $(LDLIBS_CURSES) $(LDLIBS_HAIKU)
+
+DISTFILES = src nnn.1 Makefile README.md LICENSE VERSION.mk
+SRC = src/nnn.c
+HEADERS = src/nnn.h
+BIN = nnn
+OBJS := nnn.o $(OBJS_HAIKU)
+
+all: $(BIN)
+
+ifeq ($(shell uname -s), Haiku)
+$(OBJS_HAIKU): $(SRC_HAIKU)
+       $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
+endif
+
+nnn.o: $(SRC) $(HEADERS)
+       $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
+
+$(BIN): $(OBJS)
+       $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+# targets for backwards compatibility
+debug: $(BIN)
+norl: $(BIN)
+noloc: $(BIN)
+
+install: all
+       $(INSTALL) -m 0755 -d $(DESTDIR)$(PREFIX)/bin
+       $(INSTALL) -m 0755 $(BIN) $(DESTDIR)$(PREFIX)/bin
+       $(INSTALL) -m 0755 -d $(DESTDIR)$(MANPREFIX)/man1
+       $(INSTALL) -m 0644 $(BIN).1 $(DESTDIR)$(MANPREFIX)/man1
+
+uninstall:
+       $(RM) $(DESTDIR)$(PREFIX)/bin/$(BIN)
+       $(RM) $(DESTDIR)$(MANPREFIX)/man1/$(BIN).1
+
+strip: $(BIN)
+       $(STRIP) $^
+
+dist:
+       mkdir -p nnn-$(VERSION)
+       $(CP) -r $(DISTFILES) nnn-$(VERSION)
+       mkdir -p nnn-$(VERSION)/misc
+       $(CP) -r misc/haiku nnn-$(VERSION)/misc
+       tar -cf nnn-$(VERSION).tar nnn-$(VERSION)
+       gzip nnn-$(VERSION).tar
+       $(RM) -r nnn-$(VERSION)
+
+clean:
+       $(RM) -f $(BIN) $(OBJS) nnn-$(VERSION).tar.gz
+
+skip: ;
+
+.PHONY: all debug install uninstall strip dist clean
diff --git a/misc/haiku/haiku_interop.h b/misc/haiku/haiku_interop.h
new file mode 100644 (file)
index 0000000..b422412
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct haiku_nm_t *haiku_nm_h;
+haiku_nm_h haiku_init_nm();
+void haiku_close_nm(haiku_nm_h hnd);
+int haiku_watch_dir(haiku_nm_h hnd, const char *path);
+int haiku_stop_watch(haiku_nm_h hnd);
+int haiku_is_update_needed(haiku_nm_h hnd);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/misc/haiku/nm.cpp b/misc/haiku/nm.cpp
new file mode 100644 (file)
index 0000000..ede1d37
--- /dev/null
@@ -0,0 +1,83 @@
+#include <Directory.h>
+#include <Looper.h>
+#include <NodeMonitor.h>
+#include <MessageFilter.h>
+
+#include "haiku_interop.h"
+
+filter_result dir_mon_flt(BMessage *message, BHandler **hnd, BMessageFilter *fltr) {
+       (void) hnd;
+       (void) fltr;
+
+       if (message->what == B_NODE_MONITOR) {
+               int32 val;
+               message->FindInt32("opcode", &val);
+
+               switch (val) {
+                       case B_ENTRY_CREATED:
+                       case B_ENTRY_MOVED:
+                       case B_ENTRY_REMOVED:
+                               return B_DISPATCH_MESSAGE;
+               }
+       }
+
+       return B_SKIP_MESSAGE;
+}
+
+class DirectoryListener : public BLooper {
+public:
+       bool recv_reset() {
+               Lock();
+               bool val = _ev_on;
+               _ev_on = false;
+               Unlock();
+
+               return val;
+       }
+private:
+       void MessageReceived(BMessage * message) override {
+               Lock();
+               _ev_on = true;
+               Unlock();
+               BLooper::MessageReceived(message);
+       }
+
+       bool _ev_on = false;
+};
+
+struct haiku_nm_t {
+       haiku_nm_t() {
+               dl = new DirectoryListener();
+               flt = new BMessageFilter(B_PROGRAMMED_DELIVERY, B_LOCAL_SOURCE, dir_mon_flt);
+               dl->AddCommonFilter(flt);
+               dl->Run();
+       }
+
+       DirectoryListener *dl;
+       BMessageFilter *flt;
+       node_ref nr;
+};
+
+haiku_nm_h haiku_init_nm() {
+       return new haiku_nm_t();
+}
+
+void haiku_close_nm(haiku_nm_h hnd) {
+       delete hnd->flt;
+       // This is the way of deleting a BLooper
+       hnd->dl->PostMessage(B_QUIT_REQUESTED);
+       delete hnd;
+}
+int haiku_watch_dir(haiku_nm_h hnd, const char *path) {
+       BDirectory dir(path);
+       dir.GetNodeRef(&(hnd->nr));
+
+       return watch_node(&(hnd->nr), B_WATCH_DIRECTORY, nullptr, hnd->dl);
+}
+int haiku_stop_watch(haiku_nm_h hnd) {
+       return watch_node(&(hnd->nr), B_STOP_WATCHING, nullptr, hnd->dl);
+}
+
+int haiku_is_update_needed(haiku_nm_h hnd) {
+       return hnd->dl->recv_reset();
+}
diff --git a/misc/haiku/nnn-master.recipe b/misc/haiku/nnn-master.recipe
new file mode 100644 (file)
index 0000000..7e2e463
--- /dev/null
@@ -0,0 +1,52 @@
+SUMMARY="The missing terminal file manager for X"
+DESCRIPTION="
+nnn is a full-featured terminal file manager. It's tiny and nearly 0-config with an incredible performance.
+
+nnn is also a du analyzer, an app launcher, a batch renamer and a file picker. The plugin repository has tons of plugins and documentation to extend the capabilities further. You can plug new functionality and play with a custom keybind instantly. There's an independent (neo)vim plugin.
+
+It runs smoothly on the Raspberry Pi, Termux on Android, Linux, macOS, BSD, Cygwin, WSL and works seamlessly with DEs and GUI utilities.
+
+Visit the Wiki for concepts, program usage, how-tos and troubleshooting.
+"
+HOMEPAGE="https://github.com/jarun/nnn"
+COPYRIGHT="2016-2019 Arun Prakash Jana"
+LICENSE="BSD (2-clause)"
+REVISION="1"
+SOURCE_URI="git://github.com/jarun/nnn.git"
+
+ARCHITECTURES="x86 x86_64"
+
+PROVIDES="
+       nnn = $portVersion
+       cmd:nnn = $portVersion
+       "
+REQUIRES="
+        haiku
+       lib:libncurses
+       lib:libreadline
+        "
+
+BUILD_REQUIRES="
+        haiku_devel
+       pkgconfig
+       devel:libncurses
+       devel:libreadline
+        "
+
+BUILD_PREREQUIRES="
+       cmd:make
+       cmd:gcc
+       cmd:g++
+       cmd:ld
+       cmd:install
+"
+
+BUILD()
+{
+       make -f misc/haiku/Makefile
+}
+
+INSTALL()
+{
+       make -f misc/haiku/Makefile PREFIX=$prefix MANPREFIX=$manDir install
+}
index 46d8bf59ebbf32efc8e11b46cee5c49a2c7bda19..574c7d7de5bcdaaae91062429f03adadb8488904 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -49,6 +49,9 @@
 #include <sys/event.h>
 #include <sys/time.h>
 #define BSD_KQUEUE
+#elif defined(__HAIKU__)
+#include "../misc/haiku/haiku_interop.h"
+#define HAIKU_NM
 #else
 #include <sys/sysmacros.h>
 #endif
@@ -570,6 +573,9 @@ static struct kevent events_to_monitor[NUM_EVENT_FDS];
 static uint KQUEUE_FFLAGS = NOTE_DELETE | NOTE_EXTEND | NOTE_LINK
                            | NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE;
 static struct timespec gtimeout;
+#elif defined(HAIKU_NM)
+static bool haiku_nm_active = FALSE;
+static haiku_nm_h haiku_hnd = NULL;
 #endif
 
 /* Function macros */
@@ -1892,6 +1898,8 @@ static int nextsel(int presel)
        struct kevent event_data[NUM_EVENT_SLOTS];
 
        memset((void *)event_data, 0x0, sizeof(struct kevent) * NUM_EVENT_SLOTS);
+#elif defined(HAIKU_NM)
+// TODO: Do some Haiku declarations
 #endif
 
        if (c == 0 || c == MSGWAIT) {
@@ -1947,6 +1955,9 @@ static int nextsel(int presel)
                    && kevent(kq, events_to_monitor, NUM_EVENT_SLOTS,
                              event_data, NUM_EVENT_FDS, &gtimeout) > 0)
                        c = CONTROL('L');
+#elif defined(HAIKU_NM)
+               if (!cfg.selmode && !cfg.blkorder && haiku_nm_active && idle & 1 && haiku_is_update_needed(haiku_hnd))
+                       c = CONTROL('L');
 #endif
        } else
                idle = 0;
@@ -3250,12 +3261,25 @@ static bool xmktree(char* path, bool dir)
 
                /* Create folder from path to '\0' inserted at p */
                if (mkdir(path, 0777) == -1 && errno != EEXIST) {
+#ifdef __HAIKU__
+                       // XDG_CONFIG_HOME contains a directory
+                       // that is read-only, but the full path
+                       // is writeable.
+                       // Try to continue and see what happens.
+                       // TODO: Find a more robust solution.
+                       if (errno == B_READ_ONLY_DEVICE) {
+                               goto next;
+                       }
+#endif
                        DPRINTF_S("mkdir1!");
                        DPRINTF_S(strerror(errno));
                        *slash = '/';
                        return FALSE;
                }
 
+#ifdef __HAIKU__
+next:
+#endif
                /* Restore path */
                *slash = '/';
                ++p;
@@ -3774,7 +3798,7 @@ static int dentfill(char *path, struct entry **dents)
        if (!dp)
                goto exit;
 
-#ifdef __sun
+#if defined(__sun) || defined(__HAIKU__)
        flags = AT_SYMLINK_NOFOLLOW; /* no d_type */
 #else
        if (cfg.blkorder || dp->d_type == DT_UNKNOWN) {
@@ -3878,7 +3902,7 @@ static int dentfill(char *path, struct entry **dents)
 
                /* Copy other fields */
                dentp->t = cfg.mtime ? sb.st_mtime : sb.st_atime;
-#ifndef __sun
+#if !(defined(__sun) || defined(__HAIKU__))
                if (!flags && dp->d_type == DT_LNK) {
                         /* Do not add sizes for links */
                        dentp->mode = (sb.st_mode & ~S_IFMT) | S_IFLNK;
@@ -3926,7 +3950,7 @@ static int dentfill(char *path, struct entry **dents)
 
                        if (S_ISDIR(sb.st_mode))
                                dentp->flags |= DIR_OR_LINK_TO_DIR;
-#ifndef __sun /* no d_type */
+#if !(defined(__sun) || defined(__HAIKU__)) /* no d_type */
                } else if (dp->d_type == DT_DIR || (dp->d_type == DT_LNK && S_ISDIR(sb.st_mode))) {
                        dentp->flags |= DIR_OR_LINK_TO_DIR;
 #endif
@@ -4321,6 +4345,12 @@ begin:
                event_fd = -1;
                dir_changed = FALSE;
        }
+#elif defined(HAIKU_NM)
+       if ((presel == FILTER || dir_changed) && haiku_hnd != NULL) {
+               haiku_stop_watch(haiku_hnd);
+               haiku_nm_active = FALSE;
+               dir_changed = FALSE;
+       }
 #endif
 
        /* Can fail when permissions change while browsing.
@@ -4352,6 +4382,8 @@ begin:
                        EV_SET(&events_to_monitor[0], event_fd, EVFILT_VNODE,
                               EV_ADD | EV_CLEAR, KQUEUE_FFLAGS, 0, path);
        }
+#elif defined(HAIKU_NM)
+       haiku_nm_active = haiku_watch_dir(haiku_hnd, path) == _SUCCESS;
 #endif
 
        while (1) {
@@ -4726,6 +4758,11 @@ nochange:
                                close(event_fd);
                                event_fd = -1;
                        }
+#elif defined(HAIKU_NM)
+                       if (haiku_nm_active) {
+                               haiku_stop_watch(haiku_hnd);
+                               haiku_nm_active = FALSE;
+                       }
 #endif
                        presel = filterentries(path, lastname);
 
@@ -5852,6 +5889,12 @@ int main(int argc, char *argv[])
                xerror();
                return _FAILURE;
        }
+#elif defined(HAIKU_NM)
+       haiku_hnd = haiku_init_nm();
+       if (!haiku_hnd) {
+               xerror();
+               return _FAILURE;
+       }
 #endif
 
        /* Set nnn nesting level */
@@ -5950,6 +5993,8 @@ int main(int argc, char *argv[])
        if (event_fd >= 0)
                close(event_fd);
        close(kq);
+#elif defined(HAIKU_NM)
+       haiku_close_nm(haiku_hnd);
 #endif
 
        return _SUCCESS;