How can I random sort lines in a buffer? - sorting

I have a buffer of words and phrases in sorted order and I would like to have the lines sorted in a random order. How would I do this with either an emacs builtin function or with elisp?
For example, given
bar
elisp
emacs
foo
hello world
the quick brown fox
I would like some completely random result like:
foo
the quick brown fox
hello world
elisp
emacs
bar
or ...
hello world
elisp
bar
the quick brown fox
foo
emacs

Using Bash on GNU/Linux:
Similar to Sean's solution, select the region and then:
C-u M-| shuf
Explanation:
M-| pipes the content of selected region to the bash command shuf. shuf shuffles the lines. The prefix C-u takes the output of shuf and uses it to overwrite the selected region.

Alternatively, here is sort-lines adapted to this requirement.
I've removed the reverse argument (obviously not relevant here), and simply supplied a 'comparison' function returning a random result to sort-subr.
(defun my-random-sort-lines (beg end)
"Sort lines in region randomly."
(interactive "r")
(save-excursion
(save-restriction
(narrow-to-region beg end)
(goto-char (point-min))
(let ;; To make `end-of-line' and etc. to ignore fields.
((inhibit-field-text-motion t))
(sort-subr nil 'forward-line 'end-of-line nil nil
(lambda (s1 s2) (eq (random 2) 0)))))))
For the original:
M-x find-function RET sort-lines RET

randomize-region.el seems to do what you want.

If you don't mind shelling out to Perl, you can select the region you want to randomize, and then type C-u M-| perl -MList::Util=shuffle -e 'print shuffle <STDIN>'.
I'm sure many other popular programming languages offer similar facilities.

Related

emacs + comint-dynamic-complete-filename after '='

Editing a Bash script I want to assign a filename to a variable.
E.g. inputfile=foo.txt
With std. settings I can't complete the filename without first inserting a space after the '='.
Is there any solution to this?
First of all, comint-dynamic-complete has been obsolete since Emacs 24.1. The replacement function is completion-at-point.
Now, if you starting looking at what completion-at-point actually does in a shell script buffer, you'll eventually end up in comint anyway. In particular, the function comint--match-partial-filename looks promising for an explanation of the behavior you described.
If I read that correctly, the problem here is that "=" is considered a valid part of a filename, at least on POSIX-like systems (see variable comint-file-name-chars). So, the completion mechanism is trying to complete the filename "inputfile=/..." which it can obviously not find.
If you never use a "=" in your filenames (or you use it so rarely that the working completion outweighs other downsides), you may want to consider doing something like (setq comint-file-name-chars "[]~/A-Za-z0-9+#:_.$#%,{}-") in the shell script mode hook (if you are on a POSIX system; on Windows it would look slightly different).
Hope that helps.
You can use bash-completion assuming your not on windows. It just requires a slight modification to work in sh-mode since it uses a comint function to determine the current completion candidate.
I like this because, in addition to completing filenames there, it also will give you all the nice readline completion like command line switches, etc. Here is an example setup using company, but you could remove the company stuff, since all you really need is to add the modified completion-at-point function.
;; required packages: company bash-completion
(eval-when-compile
(require cl-lib))
;; locally redefine comint-line-beginning-position so bash-completion
;; can work in sh-mode
(defun sh-bash-completion ()
(cl-letf (((symbol-function 'comint-line-beginning-position)
#'(lambda ()
(save-excursion
(sh-beginning-of-command)
(point)))))
(let ((syntax (syntax-ppss)))
(and (not (or (nth 3 syntax)
(nth 4 syntax)))
(bash-completion-dynamic-complete)))))
;; put this in your sh-mode hook
(defun sh-completion-setup ()
;; add capf function
(add-hook 'completion-at-point-functions
'sh-bash-completion nil 'local)
(company-mode)
(make-local-variable 'company-backends)
;; use company completion-at-point
(delq 'company-capf company-backends)
(cl-pushnew 'company-capf company-backends)
(setq-local company-transformers
'(company-sort-by-backend-importance)))
(add-hook 'sh-mode-hook 'sh-completion-setup)

Use z (jump around) in Emacs to find directories

Z is a popular shell tool for jumping around commonly used directories. It uses "frecency" as a metric for determining which directory you intend to jump to based on keyword completions. So if I commonly cd to ~/.ssh, I can z ssh to jump there.
My question is how can I get the same functionality to work inside Emacs? That is, I want to be able to use ido-find-file or something similar but only have to type a few characters to jump to the directory I intended. Hopefully the solution can incorporate z itself so it makes use of the frecency metric already recorded by z.
I used z once but then I found fasd, which is inspired by autojump, z or v, and which I found much more powerful, if I remember well it is because:
it not only finds directories but also files
it can cd a result or use mplayer or your editor or another command
the completion is better, specially for zsh (again, if I remember well). The thing is, I constantly use the d alias to change directories.
Anyway, there's an emacs package to find files with it: https://github.com/steckerhalter/emacs-fasd
That's cool, but it isn't as interactive as I would like.
edit: then I had to update the package and:
(setq fasd-enable-initial-prompt nil) ;; don't ask for first query but fire fuzzy completion straight away.
There's a still a use case that isn't filled:
How to use fasd (or autojump or z) with completion in an emacs shell ?
I often use emacs' shell-mode. When I use my favorite alias d, it works, but I don't have completion at all. Here, zsh's completion is clearly missing. So I would like to use ido completion, for instance. I wrote a little function which you can easily adapt for z:
edit: finished the command and added ido completion triggered by TAB. Now type d (d followed by a space). If it keeps changing and if I manage to create a minor mode I'll post the link to my gitlab repo.
edit: I created a mode for this feature: https://gitlab.com/emacs-stuff/fasd-shell/tree/master
;; Use the fasd command line utility to change recently visited directories and more.
(defun fasd-get-path-list (pattern)
"call fasd with pattern and return the list of possibilities"
(s-split "\n" (s-trim (shell-command-to-string (format "fasd -l -R %s" pattern))))
)
(defun fasd ()
"If current shell command is `d something' call fasd"
(interactive)
(let* ((user-input (buffer-substring-no-properties (comint-line-beginning-position)
(point-max))))
(if (and (string= (substring user-input 0 2) "d ")) ;; todo: mapping to use something else than d and change directory.
(progn
;; get what is after "d "
(setq fasd-pattern (buffer-substring-no-properties (+ (comint-line-beginning-position) 2) (point-max)))
(setq fasd-command (concat "cd " (ido-completing-read "cd to: " (fasd-get-path-list fasd-pattern))))
(comint-kill-input)
(insert fasd-command)
(comint-send-input)
))))
;; Use TAB as in normal shell. Now we have even better completion than in zsh !
(define-key shell-mode-map (kbd "<tab>") 'fasd) ;; works like a charm :)
As a side note, I don't use it very often because I open shells in the directory of the current buffer with shell-here and shell-pop (a drop-down terminal like guake for gnome).
Within a project, I find projectile (Projectile) mode to be really helpful.
I use the standard keybindings C-p f or M-x projectile-find-file.
It does fuzzy matching on filenames and filters on recently used files.

Emacs line numbering performance

I've tried linum and nlinum. Both have dreadful performance on files with 100k+ lines.
$ for x in {1.100000}; do echo $x; done > 100k.txt
$ emacs -q 100k.txt
M-x load-library linum
M-x linum-mode
M-> ;; it's not too bad to go to end of file
M-< ;; now this completely locks up emacs
The same operation with editors like joe is instantaneous.
Is there any solution other than to turn off line numbers with big files (exactly the type of files that you want to navigate with line numbers - I have in mind locating error lines in concatenated Javascript files)?
Or just use a different editor?
I think you found a bug, and you may report (report-emacs-bug) it. As per Tyler comment, it may have been already solved.
Things that may help you in the meanwhile... line-number-mode, goto-line, narrow-to-region and this cheapo-number-my-lines-in-a-tmp-buffer trick:
(shell-command-on-region (point-min) (point-max)
(concat "grep -n ^ " buffer-file-name)
(get-buffer-create "*tmp-linum*") nil t)
As far as I know, both linum and its derivative nlinum number lines even if you don't see them. In the case of 100k+ lines, this can be slow if numbering an individual line takes more than a few tenths of a millisecond. For me, (Fedora 19, Emacs 24.3.1), there's no noticeable delay. Try line-num.el, which only numbers lines that are currently visible and see if it fixes the problem.
Add this to .emacs file.
(global-linum-mode 1)
Since Emacs 26 you should use [global-]display-line-numbers-mode instead.
For example:
(global-display-line-numbers-mode 1)
or:
(add-hook 'prog-mode-hook #'display-line-numbers-mode)
(Or toggle them manually via M-x.)
The line numbering for these is implemented as part of the redisplay in C code, and is therefore efficient and performs well even with extremely large buffers.
To customize this feature use:
M-x customize-group RET display-line-numbers

Accepting words from the command prompt and converting to list of strings

I want to write a code in DrRacket that accepts a multiple words from the command prompt and does converts them to a list of string. For eg. if I enter hello how do you do in the prompt, it should convert it into a list '("hello" "how" "do" "you" "do"). Is it possible in DrRacket?
i tried this:
(define inp-lst (read))
On running this code, an input bar is shown in the command promt. but when i enter the above line, the value of inp-lst turns out to be just 'hello. Can someone help?
As a first step, type your input between quotes, like this:
(define inp-lst (read))
"hello how do you do"
Now, you can create a list of strings doing this:
(regexp-split #px" " inp-lst)
> '("hello" "how" "do" "you" "do")
EDIT :
As has been pointed out in the comments, read-line might be a better alternative:
(define inp-lst (read-line))
(regexp-split #px" " inp-lst)
> '("hello" "how" "do" "you" "do")
Using read-line, you don't need to surround the typed text with quotes.
The 'read' function reads one expression which in your case it the single symbol 'hello.' Your intention is to read one line, terminated by #\newline, get a single string and then split it by #\space. Try 'read-line'

When does format actually print in Common Lisp?

I have the following Common Lisp code:
(defun micro-read-eval-print ()
(format t "Micro > ")
(let ((form (read-line)))))
When I run it, I get the following:
CL-USER> (micro-read-eval-print)
(m-quote a)
Micro > NIL
Note that I typed in "(m-quote a)", while the Lisp interpreter output "Micro > NIL".
Now, I would have expected these events to happen in the reverse order. I would have expected "Micro > " to have been printed first since the format statement comes first. Why isn't it printed first? And what do I have to do to make sure it is printed first?
Try adding
(defun micro-read-eval-print ()
(format t "Micro > ")
(finish-output)
(let ((form (read-line)))))
I believe you are encountering the buffering of standard io (stdio) which, in C, is commonly bypassed via fflush() in that language.
finish-output appears to be the Common Lisp equivalent of C standard library's fflush.

Resources