rejeep / f.el Goto Github PK
View Code? Open in Web Editor NEWModern API for working with files and directories in Emacs
License: GNU General Public License v3.0
Modern API for working with files and directories in Emacs
License: GNU General Public License v3.0
Hi,
I was looking for a way to implement recursive mkdir
(so mkdir -p
). Since the library does not have such a function out of the box, I would like to make a feature request for this. I am not sure how to do feature requests...
I can go one step further, and propose some code which does this. I have called it f-mkdir-recursive
. It uses the sneaky f-traverse-upwards
function and FILO (push
/pop
). If it is good, quality-wise, I would like to contribute it to f.el
.
(defun f-mkdir-recursive (dir &optional ack-p)
"Recursively create a directory if it doesn't already exist. The second argument prints
an acknowledgment with the path of the newly created directory."
(interactive)
(let (dirs-to-mkdir)
(f-traverse-upwards
(lambda (path)
(let ((f-exists-p (f-exists? path)))
(unless f-exists-p
(push path dirs-to-mkdir))
f-exists-p))
dir)
(dolist (dir-to-mkdir dirs-to-mkdir)
(f-mkdir dir-to-mkdir))
(when (and ack-p dirs-to-mkdir)
(message "Created directory %s." dir))))
All suggestions about how to make the function more efficient are super welcome. And if the maintainers think I can contribute to f.el
, I'll be happy to! I just don't know how contributing code works in terms of the git commands etc....
EDIT: I renamed the function from f-mkdir-p
to f-mkdir-recursive
since -p
in elisp is used for other things (I am still not clear on what these things are, but they definitely don't include recursion).
You may want to apply file-truename
before comparing the paths, to resolve all intermediate symbolic links.
No response
Hi. I've been getting an error when updating recently. I suspect that this is because shortdoc is only available for more recent versions of Emacs (I'm using version 27.2).
When updating over the last couple of weeks I get following output.
`Compiling internal form(s) at Wed Jun 8 07:35:09 2022
Leaving directory ‘/home/david/.emacs.d/elpa/f-20220607.1618’
Compiling file /home/david/.emacs.d/elpa/f-20220607.1618/f-shortdoc.el at Wed Jun 8 07:35:09 2022
Entering directory ‘/home/david/.emacs.d/elpa/f-20220607.1618/’
f-shortdoc.el:31:1:Error: Cannot open load file: No such file or directory, shortdoc
Compiling file /home/david/.emacs.d/elpa/f-20220607.1618/f.el at Wed Jun 8 07:35:09 2022`
master
27.2
No response
Should functionality related to chmod
and chown
introduced? Making files executable, for example. Emacs has set-file-modes
, but it requires an integer for a 2nd argument, which is unintuitive.
Emacs master (and the pretest for 26) have changed the semantics of various file operations due to security concerns, causing several f.el
tests to fail. Specifically:
$ make EMACS=/home/p/emacs-master/src/emacs
rm -f f.elc
make unit
make[1]: Entering directory '/home/p/f.el'
cask exec ert-runner
...........................Test f-copy-contents-test/copy-directory backtrace:
copy-file("/home/p/f.el/test/playgrou
(if (f-file\? from) (copy-file from to) (if (> emacs-major-version 2
(if f--guard-paths (if (---truthy\? (let (needle) (let ((list f--gua
f-copy("/home/p/f.el/test/playground/
(let ((it (car list))) (f-copy it to))
(while list (let ((it (car list))) (f-copy it to)) (setq it-index (1
(let ((list (f-entries from)) (it-index 0)) (while list (let ((it (c
f-copy-contents("from" "to")
(let ((default-directory f-test/playground-path)) (mapc (function (l
(closure (t) nil (let ((default-directory f-test/playground-path)) (
ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
ert-run-test(#s(ert-test :name f-copy-contents-test/copy-directory :
ert-run-or-rerun-test(#s(ert--stats :selector (and t) :tests [#s(ert
ert-run-tests((and t) (lambda (event-type &rest event-args) (cond ((
ert-runner/run-tests-batch((and t))
(let ((stats (ert-runner/run-tests-batch selector))) (kill-emacs (if
ert-runner/run-tests-batch-and-exit((and t))
(if ert-runner-verbose (ert-runner/run-tests-batch-and-exit ert-runn
(let ((test-files (ert-runner--test-files tests)) (test-helper (f-ex
ert-runner/run()
apply(ert-runner/run nil)
commander--handle-command(nil)
commander-parse(nil)
(if commander-parsing-done nil (commander-parse (or commander-args (
eval-buffer(#<buffer *load*> nil "/home/p
load-with-code-conversion("/home/p/f.
load("/home/p/f.el/.cask/27.0/elpa/er
command-line-1(("-scriptload" "/home/p
command-line()
normal-top-level()
Test f-copy-contents-test/copy-directory condition:
(file-already-exists "File already exists" "/home/p/f.el/test/playground/to")
F...Test f-copy-test/copy-absolute-dir-exists backtrace:
make-directory-internal("/home/p/f.el
make-directory("/home/p/f.el/test/pla
copy-directory("/home/p/f.el/test/pla
(if (> emacs-major-version 23) (copy-directory from to) (if (f-dir\?
(if (f-file\? from) (copy-file from to) (if (> emacs-major-version 2
(if f--guard-paths (if (---truthy\? (let (needle) (let ((list f--gua
f-copy("/home/p/f.el/test/playground/
(let ((default-directory f-test/playground-path)) (mapc (function (l
(closure (t) nil (let ((default-directory f-test/playground-path)) (
ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
ert-run-test(#s(ert-test :name f-copy-test/copy-absolute-dir-exists
ert-run-or-rerun-test(#s(ert--stats :selector (and t) :tests [#s(ert
ert-run-tests((and t) (lambda (event-type &rest event-args) (cond ((
ert-runner/run-tests-batch((and t))
(let ((stats (ert-runner/run-tests-batch selector))) (kill-emacs (if
ert-runner/run-tests-batch-and-exit((and t))
(if ert-runner-verbose (ert-runner/run-tests-batch-and-exit ert-runn
(let ((test-files (ert-runner--test-files tests)) (test-helper (f-ex
ert-runner/run()
apply(ert-runner/run nil)
commander--handle-command(nil)
commander-parse(nil)
(if commander-parsing-done nil (commander-parse (or commander-args (
eval-buffer(#<buffer *load*> nil "/home/p
load-with-code-conversion("/home/p/f.
load("/home/p/f.el/.cask/27.0/elpa/er
command-line-1(("-scriptload" "/home/p
command-line()
normal-top-level()
Test f-copy-test/copy-absolute-dir-exists condition:
(file-already-exists "File exists" "/home/p/f.el/test/playground/bar")
F..Test f-copy-test/copy-relative-dir-exists backtrace:
make-directory-internal("/home/p/f.el
make-directory("/home/p/f.el/test/pla
copy-directory("foo" "bar")
(if (> emacs-major-version 23) (copy-directory from to) (if (f-dir\?
(if (f-file\? from) (copy-file from to) (if (> emacs-major-version 2
(if f--guard-paths (if (---truthy\? (let (needle) (let ((list f--gua
f-copy("foo" "bar")
(let ((default-directory f-test/playground-path)) (mapc (function (l
(closure (t) nil (let ((default-directory f-test/playground-path)) (
ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
ert-run-test(#s(ert-test :name f-copy-test/copy-relative-dir-exists
ert-run-or-rerun-test(#s(ert--stats :selector (and t) :tests [#s(ert
ert-run-tests((and t) (lambda (event-type &rest event-args) (cond ((
ert-runner/run-tests-batch((and t))
(let ((stats (ert-runner/run-tests-batch selector))) (kill-emacs (if
ert-runner/run-tests-batch-and-exit((and t))
(if ert-runner-verbose (ert-runner/run-tests-batch-and-exit ert-runn
(let ((test-files (ert-runner--test-files tests)) (test-helper (f-ex
ert-runner/run()
apply(ert-runner/run nil)
commander--handle-command(nil)
commander-parse(nil)
(if commander-parsing-done nil (commander-parse (or commander-args (
eval-buffer(#<buffer *load*> nil "/home/p
load-with-code-conversion("/home/p/f.
load("/home/p/f.el/.cask/27.0/elpa/er
command-line-1(("-scriptload" "/home/p
command-line()
normal-top-level()
Test f-copy-test/copy-relative-dir-exists condition:
(file-already-exists "File exists" "/home/p/f.el/test/playground/bar")
F........................................................................................................Test f-move-test/move-absolute-path backtrace:
rename-file("/home/p/f.el/test/playgr
(if f--guard-paths (if (---truthy\? (let (needle) (let ((list f--gua
f-move("/home/p/f.el/test/playground/
(let ((default-directory f-test/playground-path)) (mapc (function (l
(closure (t) nil (let ((default-directory f-test/playground-path)) (
ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
ert-run-test(#s(ert-test :name f-move-test/move-absolute-path :docum
ert-run-or-rerun-test(#s(ert--stats :selector (and t) :tests [#s(ert
ert-run-tests((and t) (lambda (event-type &rest event-args) (cond ((
ert-runner/run-tests-batch((and t))
(let ((stats (ert-runner/run-tests-batch selector))) (kill-emacs (if
ert-runner/run-tests-batch-and-exit((and t))
(if ert-runner-verbose (ert-runner/run-tests-batch-and-exit ert-runn
(let ((test-files (ert-runner--test-files tests)) (test-helper (f-ex
ert-runner/run()
apply(ert-runner/run nil)
commander--handle-command(nil)
commander-parse(nil)
(if commander-parsing-done nil (commander-parse (or commander-args (
eval-buffer(#<buffer *load*> nil "/home/p
load-with-code-conversion("/home/p/f.
load("/home/p/f.el/.cask/27.0/elpa/er
command-line-1(("-scriptload" "/home/p
command-line()
normal-top-level()
Test f-move-test/move-absolute-path condition:
(file-error "Renaming" "Is a directory" "/home/p/f.el/test/playground/foo.txt" "/home/p/f.el/test/playground/bar")
FTest f-move-test/move-relative-path backtrace:
rename-file("foo.txt" "bar" t)
(if f--guard-paths (if (---truthy\? (let (needle) (let ((list f--gua
f-move("foo.txt" "bar")
(let ((default-directory f-test/playground-path)) (mapc (function (l
(closure (t) nil (let ((default-directory f-test/playground-path)) (
ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
ert-run-test(#s(ert-test :name f-move-test/move-relative-path :docum
ert-run-or-rerun-test(#s(ert--stats :selector (and t) :tests [#s(ert
ert-run-tests((and t) (lambda (event-type &rest event-args) (cond ((
ert-runner/run-tests-batch((and t))
(let ((stats (ert-runner/run-tests-batch selector))) (kill-emacs (if
ert-runner/run-tests-batch-and-exit((and t))
(if ert-runner-verbose (ert-runner/run-tests-batch-and-exit ert-runn
(let ((test-files (ert-runner--test-files tests)) (test-helper (f-ex
ert-runner/run()
apply(ert-runner/run nil)
commander--handle-command(nil)
commander-parse(nil)
(if commander-parsing-done nil (commander-parse (or commander-args (
eval-buffer(#<buffer *load*> nil "/home/p
load-with-code-conversion("/home/p/f.
load("/home/p/f.el/.cask/27.0/elpa/er
command-line-1(("-scriptload" "/home/p
command-line()
normal-top-level()
Test f-move-test/move-relative-path condition:
(file-error "Renaming" "Is a directory" "/home/p/f.el/test/playground/foo.txt" "/home/p/f.el/test/playground/bar")
F........................................................................................
Ran 229 tests in 29.509 seconds
5 unexpected results:
FAILED f-copy-contents-test/copy-directory
FAILED f-copy-test/copy-absolute-dir-exists
FAILED f-copy-test/copy-relative-dir-exists
FAILED f-move-test/move-absolute-path
FAILED f-move-test/move-relative-path
Makefile:13: recipe for target 'unit' failed
make[1]: *** [unit] Error 1
make[1]: Leaving directory '/home/p/f.el'
Makefile:7: recipe for target 'test' failed
make: *** [test] Error 2
It's considered an absolute path by the function underlying f-absolute?
, and so f-split
prepends a path separator.
(f-split "~/.zshrc") ;; => ("/" "~" ".zshrc")
A few things stand out as left over from #86 (and #89), but I'm not completely familiar with f.el
and intended behaviour.
file-name-as-directory
calls in tests (added by #86) should be removed as part of #89.f-dirname
/f-parent
should probably return a trailing slash, and thus tests modifications in #89 should be reverted. This has knock-on effects for several other functions that could be quite tricky.f-filename
should return a trailing slash for inputs with a trailing slash. It sounds odd to have a function called f-filename
return a directory, but it seems intended to be equivalent to basename. This also has knock-on effects for other functions.I haven't checked the full range of tests but neither of those PRs added many tests, whilst behaviour of underlying Emacs functions became more subtle and behaviour of f.el
changed in some cases. I'm looking for @phst to add to the discussion, since they seem to know more about it than I do and were responsible for those PRs. #70 also seems relevant.
No response
Loading f.el
on Emacs 28+ shouldn't be slower than older versions
Requiring the uncompiled "f-shortdoc" make loading "f.el" ~3 times slower.
Just using an newer version of Emacs makes startup a bit slower doesn't sound right.
master
master
With s, dash, shortdoc already loaded. f, f-short aren't.
(benchmark-progn (require 'f-shortdoc))
> Elapsed time: 0.001459s
(benchmark-progn (require 'f))
> Elapsed time: 0.000756s
Given
artemis ~/src/f-el % git diff v0.17.3..v0.18.1
diff --git a/f.el b/f.el
index 8d3223e..f2e077c 100644
--- a/f.el
+++ b/f.el
@@ -4,7 +4,7 @@
;; Author: Johan Andersson <[email protected]>
;; Maintainer: Johan Andersson <[email protected]>
-;; Version: 0.17.3
+;; Version: 0.18.1
;; Keywords: files, directories
;; URL: http://github.com/rejeep/f.el
;; Package-Requires: ((s "1.7.0") (dash "2.2.0"))
did you perhaps forget to merge in the development branch before tagging the new release? Thanks.
Wouldn't it be more convenient it if would just return nil
?
There is a simple test for f-up
:
(ert-deftest f-up-test/true ()
(with-playground
(should (equal f-test/playground-path (f-up (lambda (path) t))))))
This test seems to imply that dir
and (f-up (lambda (path) t) dir)
should always be equal, which seems reasonable. However, the current implementation of f-up
doesn't have this invariant for top-level directories:
(mapcar
(lambda (dir)
(list dir (f-up (lambda (path) t) dir)))
'("/usr/share" "/usr" "/"))
;; Result:
(("/usr/share" "/usr/share") ("/usr" "/") ("/" "/"))
This is version 20150113.24 of f.el on Emacs 25.0.50.1.
Hello,
Version 0.18.0 has not yet been released, but the f.el repository has a v0.18.0 tag. This is confusing Debian tooling which thinks that a new upstream version is available. I would really appreciate it if this false tag could be removed:
git tag -d v0.18.0
git push origin :refs/tags/v0.18.0
Thanks.
Sean
The new release is tagged 1.18.1, but in f.el the release is given as 0.18.1. Which is correct? Since the previous release was 0.17.3 I assume that the new one is 0.18.1 and the tag is incorrect, but please confirm. Thanks!
Is it a good idea to implement f-append
function?
This is a terrific and useful package, thanks.
There are times when I need to manipulate directory names that do not (yet) exist. But f-slash, and thus f-full, do not append the slash in this case. I'm not sure whether f-slash should have the requirement of an existing directory. I think I prefer that it not, but I can see arguments both ways. However, if there is that requirement, I think it should be made clear in the documentation.
If the existence requirement is kept for f-slash, it might be a nice alternative to allow an optional argument to force the behavior:
(defun f-slash (path &optional if-not-exists)
"Append slash to PATH unless one is already present.
A slash will not be appended for a non-existent directory path
unless IF-NOT-EXISTS is non-nil. Some functions, such as
`call-process' requires there to be an ending slash."
(if (or (f-dir? path) if-not-exists)
(file-name-as-directory path)
path))
This could be propagated to f-full (e.g., as-directory
) which is the only function calling f-slash. I see that you need the requirement for f-full so that it can distinguish an arbitrary path as file or directory. However, it seems to me that that is where the requirement belongs rather than in f-slash, which by name just adds a slash. (UPDATED)
One could, of course, just call file-name-as-directory in this case, but we might as
well keep the advantage of a unified interface.
hi,
i come here via trying to install https://github.com/mrkkrp/ebal,
which currently refers to 0.18.0 of your package.
i found one commit, 7003428, but the version of f.el within the file is 0.17.2
Hi!
I constructed the following little helper function to help me fill up my projectile index just now:
(defun my/find-git-projects (dir)
"Find all git projects under DIR."
(mapcar #'f-dirname
(f-directories "~/Documents/"
(lambda () (equal (f-filename dir) ".git"))
t)))
Unfortunately I get the following error:
f--collect-entries: Opening directory: Permission denied, c:/Users/mattias.bengtsson/AppData/Local/Application Data
Would it be possible to teach f-directories to optionally ignore directories it can't reach due to permissions instead of erroring out?
What about f-current-library
which returns the file name of the currently loaded library?
I should cover the following three cases:
eval-buffer
.An implementation of this is already contained in cask-cli.el
.
Hi, thanks for the great package! Are you planning on making a new stable/versioned release soon? It'd be really nice to have a stable version assigned to the recent backwards incompatible changes.
I am trying to join two path using f-join
function.
(message "%s" (f-join "C:/Program Files (x86)/Microsoft Visual Studio/" "/Community/VC/Tools/MSVC/"))
Output
c:/Community/VC/Tools/MSVC/
Expected Output
C:/Program Files (x86)/Microsoft Visual Studio/Community/VC/Tools/MSVC/
Any idea? 😕
I beleaved that f-join
behaves like expand-file-name
(or concat
if args are valid). However it does not currently:
(expand-file-name "dir/" "/path/to") ; => "/path/to/dir/"
(f-join "/path" "to" "dir/") ; => "/path/to/dir"
(file-name-as-directory (f-join "/path" "to" "dir/")) ; => "/path/to/dir/"
Sometimes this difference causes bugs. IMHO lisp functions should not depend on whether directory name ends slash or not, but in practice, for example,
(setq auto-save-list-file-prefix (f-join "~" ".emacs.d" "auto-save-list/"))
will cause unpleasant result. I feel the name auto-save-list-file-prefix
is fair and the "bug" is due to the difference between expected behavior from the name f-join
and its actual behavior.
It is easy to fix but the change breaks adjointness (relation nearly inverse) of f-join
and f-split
. How do you think of it?
If you agree, I'll send PR. If not, please declare that and note this case in doc-string and test.
The ebal
package depends on the f-swap-ext function that isn't in any released version of f
. That means it can't depend on anything but a melpa
version.
Hi there,
In this interesting discussion with Alexander Miller, he mentioned that directory-files
is faster when called in a temp buffer. This quick test seems to show that it is indeed:
#+BEGIN_SRC elisp
(defun f--collect-entries--tb (path recursive)
(with-temp-buffer
(let (result
(entries
(-reject
(lambda (file)
(or
(equal (f-filename file) ".")
(equal (f-filename file) "..")))
(directory-files path t))))
(cond (recursive
(-map
(lambda (entry)
(if (f-file? entry)
(setq result (cons entry result))
(when (f-directory? entry)
(setq result (cons entry result))
(setq result (append result (f--collect-entries entry recursive))))))
entries))
(t (setq result entries)))
result)))
(list (cons "without temp buffer"
(progn
(garbage-collect)
(benchmark-run-compiled 100
(f--collect-entries "~/.emacs.d" nil))))
(cons "with temp buffer"
(progn
(garbage-collect)
(benchmark-run-compiled 100
(f--collect-entries--tb "~/.emacs.d" nil)))))
#+END_SRC
#+RESULTS:
| without temp buffer | 0.31999160200000004 | 0 | 0.0 |
| with temp buffer | 0.191897104 | 0 | 0.0 |
I thought I should let you know in so that it could be added to f--collect-entries
. Seems like a nice, free optimization. :)
Thanks for your work on f.el!
If the directory tree being traversed by f-entries has any unreadable directories,
f-entries still tries to recurse into it and throws an error. Here ~/.cache/dconf is
not readable by the emacs process, and f-entries returns no results:
ELISP> (f-entries "/home/work/.cache/" nil t)
*** Eval error *** Opening directory: Permission denied, /home/work/.cache/dconf
The expected result should be that unreadable directories are in the results, but no recursion is performed on them.
As I was studying your library, I was wondering if in this case buffer-substring-no-properties
is redundant for f-read-bytes
?
(defun f-read-bytes (path)
"Read binary data from PATH.
Return the binary data as unibyte string."
(with-temp-buffer
(set-buffer-multibyte nil)
(setq buffer-file-coding-system 'binary)
(insert-file-contents-literally path)
(buffer-substring-no-properties (point-min) (point-max))))
Since insert-file-contents-literally
does not run find-file-hook (nor format decoding, character code conversion, automatic uncompression, and so on), wouldn't buffer-string
suffice?
In that way, buffer-string
would make it a little simpler?
Great library guys, real help.
So I've been using f-uniquify-alist
along with projectile
which is cool. I just noticed in a big project where there are 642 files and 140 directories, said function hangs when I run it with projectile-current-project-dirs
and weirdly it doesn't hang when it is run with projectile-current-project-files
. This is sort of weird when there are more files than there are directories and yet it chokes.
After some investigation, given a minimal test path list of (list "a/b/c/d/" "a/B/c/d/")
; this creates an infinite loop with (s-chop-prefix "d" "a/b/c/d/")
instead of the correct (s-chop-prefix "d/" "a/b/c/d/")
.
Hi,
I'd be grateful if you'd consider keeping the changelog in its own file (e.g. CHANGELOG.md). That way, the Debian packaging of f.el can just install that file. At present, I have to manually extract the changelog data on each release.
Thanks!
eyedropper 20150509.1345 available melpa Pick foreground and background colors at cursor or pointer.
eyuml 20141028.1527 available melpa Write textual uml diagram from emacs using yuml.me
ez-query-replace 20140810.517 available melpa a smarter context-sensitive query-replace that can be reapplied
f90-interface-b... 1.1 available gnu Parse and browse f90 interfaces
fabric 20141024.322 available melpa Launch Fabric using Emacs
face-remap+ 20150104.1358 available melpa Extensions to standard library face-remap.el'. facemenu+ 20150816.1953 available melpa Extensions to
facemenu.el'.
faces+ 20150104.1400 available melpa Extensions to `faces.el'.
It's more common in elisp to use foo-p
for predicates. Would you be willing to add these as aliases? I'm happy to write a PR.
f.el is using -sum
which was only added in 1.5.0.
On macOS, /path/to/dir
is equivalent to /path/TO/dir
because the filesystem is case insensitive but case preserving. However, the following function call returns nil instead of t:
(f-ancestor-of? "/path/to" "/path/TO/dir")
You have f-expand
. What about supporting f-contract
?
(f-contract "/home/wpcarro/file.txt") ;; => "~/file.txt"
I often need this to write predicates that work across my different machines that return different values for ~
. I'm happy to create a PR if you're open to the idea.
If this already exists, and I've missed the function, please let me know!
Hi, I wanted to preface this by saying that this is neither a feature request nor a bug report, and more like a cry for help.
I wanted my little script to help me find directories that contain .org
files. I also wanted these directories to not be at any point, hidden. To this end, I am glad that I found f.el
, which did all the heavy-lifting.
Here are the few lines of code I wrote. Bear in mind that the following are literally the first few lines of Emacs Lisp I have written, ever, which is why I'm hoping to get some feedback. I also never took a course or went through a beginners tutorial on Emacs Lisp; and instead just decided to dive right into it just by looking particular things up. It's probably not the most Lisp-y (if there's even such a thing) and very verbose, but please bear with me!
(defun is-dotstring (str)
(integerp(string-match-p "^\\.\\w.*$" str))
)
(defun path-has-dotstring (path)
(consp (member t (mapcar #'is-dotstring (f-split path))))
)
(defun dir-has-filetype (path filetype)
(consp (f--files path (equal (f-ext it) filetype)))
)
(f-directories root_directory (lambda (dir) (and (not (path-has-dotstring dir)) (dir-has-filetype dir "org"))) t)
So for the root_directory
that I specified, this piece of code took somewhere from 1-2 minutes to run. Because I also hope to run this at the startup of Emacs, this speed won't do.
On the other hand, something like the Linux tool find
achieved the same thing in less than 5 seconds.
find [root_directory] -name '*.org' -not -path '*/.*' -printf '%h\n' | sort -u
Of course, I am not claiming that I wrote them the same way, so differences in performance is expected.
However, I do want to do this in Emacs, so I'm wondering if there are any ways I could improve on it, using f.el
or otherwise (e.g. piping in the results from find
). In the case of f-directories
, I understand that every directory is visited recursively, even if it is many layers deep into a hidden directory (e.g. .git
). Perhaps one way is to write the program in a way that prevents this from happening.
Any help is greatly appreciated! Thanks!
f.el
is great! I just need help using it!
It could be implemented doing foo, bar, and baz
(f-parent "/foo/bar/baz") ;; => "/foo/bar"
(f-parent "foo/bar/baz") ;; => "foo/bar/"
I find the kind of "reverse symmetry" pretty funny :D
Anyway, this also breaks f-common-parent
. I tried wrapping it with f-slash
but that doesn't append the final slash in some cases, which leaves me puzzled as to what is its purpose then?
Hi,
I found out that f--collecting-entries
function takes quite a lot of time when it recursively collects entries (where a directory has many entries). I wanted to use wait-timeout
to wrap f--collecting-entries
but it doesn't work with the current implementation because f--collecting-entries
never wait for an input.
My current work-around is to insert (sit-for 0.000001)
at https://github.com/rejeep/f.el/blob/master/f.el#L425 . I'm wondering whether there is a better solution for my problem. Any suggestion is welcome.
As far as I can tell there's no reason the path
argument to f-traverse-upwards
needs to actually exist, but this is checked beforehand anyway
Any chance of a "newer" function? ie (if (f-newer fileA fileB) ) ... fileA is newer than fileB...
Currently f-up
returns the file system root, if the given predicate never returns non-nil.
Hence, the caller can't use the truthyness of the return value to determine whether the predicate ever matched. Instead, they need to check the return value with f-root?
and with the predicate (in case that the file system root could have matched).
That is, instead of (when (f-up #'my-predicate directory) …)
, you need to use (let ((ancestor (f-up #'my-predicate directory))) (when (or (not (f-root? ancestor)) (my-predicate ancestor) …)
.
I think f-up
should be deprecated, and replaced with a function f-traverse-upwards
that behaves the same, but returns nil, if the predicate never returned non-nil.
Hi
Maybe I am misreading things, but I just noticed that Dash on elpa is at version: 2.12.0. However, f on melpa "Requires: dash-2.2.0".
I noticed this when running emacs -Q and package-initialize
Unable to activate package ‘f’.
Required package ‘dash-2.2.0’ is unavailable
When I run emacs (without the -Q) this does not seem to be a problem (and that is confusing).
ELISP> (f-join "a" "/b")
"../../../../b"
ELISP> (cd "~")
"/home/sindikat/"
ELISP> (f-join "a" "/b")
"../../b"
f-join
behaves strange when meets an argument starting with slash, depending on a current directory in Emacs. In Python, for example, os.path.join
simply discards all previous arguments when meets an argument starting with slash. Do you think it is better to make f-join
behave like Python's?
Hi,
How could one simulate the following cp
action:
cp -r ~/path/to/source/ ~/path/to/target/
The following syntax does not have the same effect:
(f-copy "~/path/to/source/" "~/path/to/target/"
As it copies source
dir into target
dir.
Thank you so much for f.el
.
If a non existing directory or symlink is passed as argument to f-slash
it will append a slash.
Would it be possible to add something like f-stat
, which would return Posix stat
metadata about a given path?
Right now one would need to have a system call to fecth that metadata.
(f-stat "file.txt")
;; device 16777222
;; inode 4080486
;; mode 33188
;; nlink 1
;; uid 501
;; gid 20
;; rdev 0
;; size 1500520
;; atime 1451758319
;; mtime 1423242348
;; ctime 1451831422
;; blksize 4096
;; blocks 2936
;; link nil
I find f.el
extremely useful. Thank you so much.
It would be nice to add an f-split
function that does the inverse of f-join
, so (f-split "foo/bar/baz.txt")
would return ("foo" "bar" "baz.txt")
.
I've looked through the docs, but I don't think f.el currently offers this functionality.
(f-join (f-root) "C:\\Users\\61169.html")
Surprisingly, this gives me the following when executed on linux:
ssh: Could not resolve hostname c: Name or service not known
and
Tramp: Waiting for prompts from remote shell...failed
Tramp: Opening connection for C using scp...failed
tramp-file-name-handler: Tramp failed to connect. If this happens repeatedly, try
‘M-x tramp-cleanup-this-connection’
I understand that I'm feeding f-join
with garbage but I think it should nevertheless not attempt to open connections.
Currently, f-ext is described as follows:
Return the file extension of PATH.
However, it uses file-name-extension
, which strips version numbers and backup suffixes. It would be nice if that fact could be mentioned as well. I fell for that today, because
(f-files "/some/path"
(lambda (x)
(f-ext? x "md")))
will also return all backup files (ending in "md~")
f-mkdir
returns nil.
The documentation says it returns the created path, similar to f-join
, for example.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.