(buffer-substring-no-properties) backslash handling - elisp

Good afternoon. In the text, the record
#samp{\}
, the code
(buffer-substring-no-properties (+ nach 4) (- (point) 4))
is captured here this region, at the output of the
"#samp{\\}"
function. The question is how to get the non-escaped forward slash. Thank you

"#samp{\\}" represents the string #samp{\}. It's not different to the original text.
When you ask Emacs to print the return value of buffer-substring-no-properties you are seeing the printed representation of a string -- which is equivalent to the double-quoted read syntax for strings (as you would write it in code) -- in which a single backslash must be escaped with another.
Refer to the elisp manual:
C-hig (elisp)Printed Representation
C-hig (elisp)Syntax for Strings
C-hig (elisp)Nonprinting Characters

Changes further along the code gave the result, namely, not a correction of the record of the read line, but a change in the insertion of the ill-fated line "#samp {\\}" back into the text. The function is presented
(defun zamenaOBJ (спсОбктв)
"Зменить obzx оригиналом"
(goto-char 1)
(while (re-search-forward "[Bb]jkt\\([[:digit:]]\\)+" nil t 1)
(replace-match (cdr (assoc (downcase (match-string 0)) спсОбктв)) t)))
Here is the data at the time of the error (what was received
(buffer-substring-no-properties)
and saved in the associative list
(cdr (assoc (downcase (match-string 0)) спсОбктв))
"#samp{\\}"
The error itself
(replace-match (cdr (assoc (downcase (match-string 0)) спсОбктв)) t)
Invalid use of ‘\’ in replacement text
If it was written like this:
(replace-match (prin1-to-string (cdr (assoc (downcase (match-string 0)) спсОбктв)) t))
все замены по тексту были окружены двойной кавычкой, если же указывался аргумент noescape в t для prin1-to-string:
(replace-match (prin1-to-string (cdr (assoc (downcase (match-string 0)) спсОбктв)) t) t)
or
(replace-match (princ (cdr (assoc (downcase (match-string 0)) спсОбктв)) t))
the error came back again
Solved by adding the second argument literal replace-match
(replace-match (cdr (assoc (downcase (match-string 0)) спсОбктв)) t t)

Related

Why do I get "application: not a procedure" with this for loop in Racket?

The following code reads a csv file and based on its content generates a Prolog program:
#!/usr/bin/env racket
#lang racket/base
(define (overwrite-s-to-f fname s); Will create fname and write overwriting the previous content.
(with-output-to-file #:exists 'truncate fname (lambda () (displayln s))))
(define (c-o-a-line-to-f fname s); Will append a string to fname or create it if does not exist. Appends a new line.
(with-output-to-file #:exists 'append fname (lambda () (displayln s))));
(define fname "women.csv")
(define pl-fname "females-by-Racket.pl")
(require racket/file)
(define content (file->lines fname))
(define disc-line (string-append ":-discontiguous(" (string-replace (car content) "Name," "") ").\n"))
(overwrite-s-to-f pl-fname disc-line)
(define list-of-verbs (string-split (string-replace (car content) "Name," "") ","))
(require racket/string racket/system)
(for ((row content));content is a list of strings
(let ((list-of-cs (string-split row ",")))
(when (equal? (car (cdr list-of-cs)) "+")
(displayln row)(let ((cmd (string-append "awesome("(car list-of-cs)").")))(c-o-a-line-to-f pl-fname cmd)(displayln cmd)))
(when (equal? (car (cdr (cdr list-of-cs))) "+")(displayln row)(let ((cmd (string-append "and_intelligent("(car list-of-cs)").")))
(c-o-a-line-to-f pl-fname cmd)(displayln cmd))))); TODO: when for each columns 2-last of women.csv
The content of women.csv:
Name,awesome,and_intelligent,performed_once,extreme1,extreme2,extreme3,extreme4,donkey_thing,dark_eyes,pigmented_face,pigmented_genitals,bleached,had_no_surgeries,has_augmented_breasts
adriana_chechik,+,,,+,?,+,+,,-,,,,,
alysa_gap,+,,,,?,+,+,,-,,,,,
anna_de_ville,+,,,,,+,+,,+,-,+,-,-,
aurora_jolie,+,+,,,,,,,+,+,+,,+,
autumn_falls,,,,,,,,,+,+,-,+,+,
casey_calvert,+,,,,,,,,+,+,+,,,
dahlia_sky,+,,,,,,+,,,,,,,
dominica_lito,+,,,,,,+,,,,,,,
ella_knox,,,,,,,,,+,+,+,,+,
isabella_clark,+,,,,,,+,,,,,,,
jade_kush,,,,,,,,,+,+,,,+,
juelz_ventura,+,,,,,+,,,-,-,,,-,+
kapri_styles,,,,,,,,,+,,+,,,
kristina_milan,,,,,,,,,+,+,,,+,
kylie_sinner,+,+,,,,,,,+,,,,-,
leigh_raven,+,,,,,+,,,+,+,,,,
maserati,,,,,,,,,+,+,,,+,
miosotis,,,,,,,,,+,+,,,+,
scarlett_bloom,,,,,,,,,+,+,+,,-,
sheena_shaw,,,,,,,,,-,,+,,-,
sofia_rose,,,,,,,,,+,,,,+,
teanna_trump,+,,,,,,,,+,,+,,,
veronica_avluv,+,,,,,,+,,,,,,,
yudi_pineda,+,,,,,,,,+,+,,,,
females-by-Racket.pl is to look like so:
:-discontiguous(awesome,and_intelligent,performed_once,extreme1,extreme2,extreme3,extreme4,donkey_thing,dark_eyes,pigmented_face,pigmented_genitals,bleached,had_no_surgeries,has_augmented_breasts).
awesome(adriana_chechik).
awesome(alysa_gap).
awesome(anna_de_ville).
awesome(aurora_jolie).
and_intelligent(aurora_jolie).
awesome(casey_calvert).
awesome(dahlia_sky).
awesome(dominica_lito).
awesome(isabella_clark).
awesome(juelz_ventura).
awesome(kylie_sinner).
and_intelligent(kylie_sinner).
awesome(leigh_raven).
awesome(teanna_trump).
awesome(veronica_avluv).
awesome(yudi_pineda).
but with more predicates (up to n-1 for each woman where n is the number of columns in women.csv)
The names of the columns or the numbers thereof in women.csv are likely to be frequently changed.
That is partly why I wish to avoid manually coding for every when. The other concerns are the sheer amount of the lines to code (15 whens for each column) and the risk of error/typo.
Is it doable to loop through every cell in list-of-cs in such way that it is taken from list-of-verbs?
I've tried this but to no avail (the comment show the error message that I got):
(for ((row content))
(let ((list-of-cs (cdr (string-split row ","))))
(for ((cell list-of-cs))
; application: not a procedure; expected a procedure
; that can be applied to arguments
(set! list-of-verbs (cdr (list-of-verbs)))
(let ((verb (car list-of-verbs)))
(when (equal? cell "+")
(displayln row)
(let ((cmd (string-append verb "(" (car row) ").")))
(c-o-a-line-to-f pl-fname cmd)))
))))
named let is a useful form to be familiar with:
#lang scheme
(define (csv->attributes rows) ;; ListOfString -> ListOfString
;; produce "column-header(row-name)" for "+" entries in csv (see example)
(let ([fields (string-split (car rows) ",")])
(let next-row ([rows (cdr rows)] [result (list)])
(cond
[(null? rows) (reverse result) ]
[else
(let* ([cells (string-split (car rows) ",")]
[name (car cells)])
(let next-cell ([cells (cdr cells)] [fields (cdr fields)] [result result])
(cond
[(null? cells) (next-row (cdr rows) result) ]
[else (next-cell
(cdr cells) (cdr fields)
(if (string=? (car cells) "+")
(cons (string-append (car fields) "(" name ")") result)
result)) ]))) ]))))
(define trio '("Name,fast,slow,sidles"
"Achilles,+,,"
"Tortoise,,+,"
"Crab,,+,+"))
Welcome to DrRacket, version 8.5 [cs].
Language: scheme, with debugging.
> (csv->attributes trio)
("fast(Achilles)" "slow(Tortoise)" "slow(Crab)" "sidles(Crab)")
>

Call of non-procedure in function definition?

I found a short introduction to Scheme online, and I'm having a bit of trouble with this function:
(define (title-style str)
(let loop ((lc #\space) (i 0) (c (string-ref str 0)))
((if (char=? lc #\space)
(string-set! str i (char-upcase c)))
(if (= (- (string-length str) 1) i)
str
(loop c (+ i 1) (string-ref str (+ i 1)))))))
(display "star wars iv: a new hope")
(display (title-style "star wars iv: a new hope"))
When I try calling it, I get this:
Error: call of non-procedure: #<unspecified>
Call history:
title-style.scm:6: loop
...
title-style.scm:1: g6 <--
That error comes from Chicken Scheme, I am also getting the same results in Chez Scheme.
It converts a string to title case, and from the error messages I got earlier, it does: call of non-procedure: "Star Wars Iv: A New Hope"
I understand what you intend to do, but that's not the right way to structure a conditional expression in Scheme. Also, right before the first if there's a misplaced opening parentheses (which is the one causing the reported error), and you have to advance the recursion in all cases. This should work for non-empty strings:
(define (title-style str)
(let loop ((lc #\space) (i 0) (c (string-ref str 0)))
(cond ((= (- (string-length str) 1) i)
str)
((char=? lc #\space)
(string-set! str i (char-upcase c))
(loop c (+ i 1) (string-ref str (+ i 1))))
(else
(loop c (+ i 1) (string-ref str (+ i 1)))))))
But still, it's not the recommended way to write a solution in Scheme, you're mutating the input string along the way, which is discouraged, and you're thinking in terms of indexes. Besides, you're imposing an extra restriction on your input: that the strings must be mutable, and not all Scheme dialects support this by default.
A functional tail-recursive style is preferred, where we create a new string as output, leaving the original input untouched and leveraging the rich library of list procedures available in the language; this is what I mean:
(define (title-style str)
(let loop ((lc #\space) (lst (string->list str)) (acc '()))
(cond ((null? lst)
(list->string (reverse acc)))
((char=? lc #\space)
(loop (car lst) (cdr lst) (cons (char-upcase (car lst)) acc)))
(else
(loop (car lst) (cdr lst) (cons (car lst) acc))))))
Either way, it works as expected:
(title-style "star wars iv: a new hope")
=> "Star Wars Iv: A New Hope"

How to get Emacs to sort lines by length?

I'd like to be able to highlight a region in Emacs and then sort the region by line length.
The closest I've found is the following code which I think will sort by length:
(sort-subr t #'forward-line #'end-of-line nil nil
(lambda (l1 l2)
(apply #'< (mapcar (lambda (range) (- (cdr range) (car range)))
(list l1 l2)))))
But I don't know how to turn this into an interactive function that lets me use it by highlighting a region. Can someone help?
You can combine the sort-lines command definition with your snippet to form a new command:
(defun sort-lines-by-length (reverse beg end)
"Sort lines by length."
(interactive "P\nr")
(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 reverse 'forward-line 'end-of-line nil nil
(lambda (l1 l2)
(apply #'< (mapcar (lambda (range) (- (cdr range) (car range)))
(list l1 l2)))))))))

Call to defmacro with a quoted symbol

I have this data structure (basically):
(setq ssm-list '(tasklist
((id . "10525295")
(name . "Inbox")
(sort_order . "0"))))
This works for getting the name:
(defun ssm-list-get-prop (list prop)
(cdr (assoc prop (car (cdr list)))))
(ssm-list-get-prop slack-one-list 'name)
What'd I like is to create a macro that will create a defun with the name ssm-list-name (or ssm-list-id) as there are actually a lot more properties in the list.
So I tried this:
(defmacro ssm-list-prop-defun (field)
`(defun ,(intern (concat "ssm-list-" field))
(one-list)
(cdr (assoc ,field (car (cdr one-list))))))
(ssm-list-prop-defun 'name)
(ssm-list-prop-defun 'id)
But the last two calls failed miserably with (wrong-type-argument characterp quote) I tried putting symbol-name in the macro but that didn't help.
Is there a way to accomplish this?
You're very close, minor edits gets you a working solution. The problem is that you're mixing symbols and strings. This will work:
(defmacro ssm-list-prop-defun (field)
;; note that concat operates on strings
`(defun ,(intern (concat "ssm-list-" field))
(one-list)
;; note that you need a symbol here, so quote the
;; result of the call to intern
;; and, if you're always using symbols,
;; might as well use assq
(cdr (assq ',(intern field) (car (cdr one-list))))))
;; pass in a string
(ssm-list-prop-defun "name")
And here's the variant that uses a symbol:
;; variant that works off a symbol
(defmacro ssm-list-prop-defun (field)
`(defun ,(intern (concat "ssm-list-" (symbol-name field)))
(one-list)
(cdr (assq ',field (car (cdr one-list))))))
(ssm-list-prop-defun name)
I think you want to read about defstruct in the cl package: (info "(cl) Structures") (or http://www.gnu.org/software/emacs/manual/html_node/cl/Structures.html#Structures)

Detecting EOF in a Binary File using Scheme

(define (read-all-input)
(local ((define line (bytes->list (read-bytes 4))))
(if (eof-object? line)
empty
(cons line (read-all-input)))))
(void (read-all-input))
The above code fails because bytes->list expects an argument of type byte string, but is given #
#lang scheme
(define (read-all-input)
(let ((b (read-bytes 4)))
(cond
((eof-object? b) empty)
(else (cons b (read-all-input)))
)))
(void (read-all-input))
This function reads bytes into a list of bytes.
I'm not really sure what you want to obtain but this here's my try:
(define read-all-input
(lambda ()
(let ((line (read-bytes 4)))
(if (eof-object? line)
'()
(cons (bytes->list line) (read-all-input))))))

Resources