* Emacs Modular Configuration: the preferable way. @ 2021-06-21 1:40 Hongyi Zhao 2021-06-21 2:56 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 6:37 ` Jean Louis 0 siblings, 2 replies; 86+ messages in thread From: Hongyi Zhao @ 2021-06-21 1:40 UTC (permalink / raw) To: help-gnu-emacs Dear all, I noticed the following instructions/tools for Emacs modular configuration: https://www.emacswiki.org/emacs/DotEmacsModular https://www.emacswiki.org/emacs/DotEmacsStructuring https://github.com/emacs-jp/init-loader There are so many ways to do this. What's the preferable way? Regards -- Assoc. Prof. Hongyi Zhao <hongyi.zhao@gmail.com> Theory and Simulation of Materials Hebei Vocational University of Technology and Engineering NO. 552 North Gangtie Road, Xingtai, China ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 1:40 Emacs Modular Configuration: the preferable way Hongyi Zhao @ 2021-06-21 2:56 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 6:40 ` Jean Louis ` (3 more replies) 2021-06-21 6:37 ` Jean Louis 1 sibling, 4 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 2:56 UTC (permalink / raw) To: help-gnu-emacs Hongyi Zhao wrote: > I noticed the following instructions/tools for Emacs modular > configuration: > > https://www.emacswiki.org/emacs/DotEmacsModular > https://www.emacswiki.org/emacs/DotEmacsStructuring > https://github.com/emacs-jp/init-loader > > There are so many ways to do this. What's the > preferable way? My personal favorite is the method below, I don't know if that's mentioned on any of your links. Note that every file is mentioned explicitly, that means if you are to search for an error (say do the so-called binary search) you don't have to comment in and out code that might have comments, headers, footers, and so on, instead you just comment out one or more filenames, and when the bug or misfeature is localized, it is as easy to enable them again. (let*((emacs-dir "~/.emacs.d") (lisp-dir (format "%s/lisp" emacs-dir)) (init-dir (format "%s/emacs-init" emacs-dir)) (erc-dir (format "%s/erc" init-dir)) (gnus-dir (format "%s/gnus" init-dir)) (ide-dir (format "%s/ide" init-dir)) (w3m-dir (format "%s/w3m" init-dir)) (dirs (list lisp-dir init-dir erc-dir gnus-dir ide-dir w3m-dir ))) (dolist (d dirs) (push d load-path) ) (let ((emacs-init-files '( abc.el align-incal.el batch.el bibtex-incal.el bike.el bmi.el buc.el buffer-menu.el caps-back.el close.el console-keys.el count.el custom-vars.el day.el dired-incal.el ecat-incal.el echo-message.el edit.el elpa.el emacs-shell.el face.el file-write-to.el file.el fill-incal.el frame-size.el geh.el get-search-string.el help-incal.el info-incal.el isbn-verify.el issn-verify.el iterate-files.el jean.el keys.el kill-path.el kill.el latex.el lights.el linux-shell.el list-quoted-functions.el man-incal.el match-data-format.el math.el measure.el minor-modes.el misc.el mode-by-filename.el mode-line.el navigate-fs-keys.el negative-subtraction.el perm.el printer.el quit.el random.el re-make-list.el replace-list.el revert-buffer.el scale.el scroll.el search-regexp-in-files.el sequence-string.el shell-cli.el show-command.el signal.el sort-incal.el spell.el street.el string.el sudo-user-path.el super.el survivor.el switch-to-buffer-regexp.el switch-to-buffer.el tabs.el test-face.el test.el time-cmp.el time-incal.el time-insert.el todo-did.el tramp-incal.el variance.el vt.el window-incal.el wood.el wrap-search.el xsel.el yank.el ))) (dolist (f emacs-init-files) (load-file (format "%s/%s" init-dir f) ))) (let ((emacs-erc-init-files '( erc-connect.el erc-incal.el erc-iterate.el erc-kill.el erc-misc.el erc-spell.el ))) (dolist (f emacs-erc-init-files) (load-file (format "%s/%s" erc-dir f) ))) (let ((emacs-gnus-init-files '( article.el browse.el gnus-incal.el gnus-server.el group-summary.el group.el mail-to-many.el mail.el mailrc.el message-dynamic.el message-incal.el moggle.el summary.el ))) (dolist (f emacs-gnus-init-files) (load-file (format "%s/%s" gnus-dir f) ))) (let ((emacs-ide-init-files '( c-and-cpp.el compile-incal.el elisp.el find-command.el html.el ide.el lisp-incal.el ))) (dolist (f emacs-ide-init-files) (load-file (format "%s/%s" ide-dir f) ))) (let ((emacs-w3m-init-files '( bookmarks.el dl.el history.el w3m-incal.el w3m-keys.el w3m-sem.el w3m-tabs.el w3m-unisearch.el ))) (dolist (f emacs-w3m-init-files) (load-file (format "%s/%s" w3m-dir f) ))) ) https://dataswamp.org/~incal/conf/.emacs -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 2:56 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 6:40 ` Jean Louis 2021-06-21 16:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 10:14 ` Arthur Miller ` (2 subsequent siblings) 3 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-21 6:40 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-06-21 05:57]: > (let*((emacs-dir "~/.emacs.d") > (lisp-dir (format "%s/lisp" emacs-dir)) > (init-dir (format "%s/emacs-init" emacs-dir)) > (erc-dir (format "%s/erc" init-dir)) > (gnus-dir (format "%s/gnus" init-dir)) > (ide-dir (format "%s/ide" init-dir)) > (w3m-dir (format "%s/w3m" init-dir)) > (dirs (list > lisp-dir pp> init-dir > erc-dir > gnus-dir > ide-dir > w3m-dir > ))) > (dolist (d dirs) > (push d load-path) ) > (let ((emacs-init-files '( > abc.el > align-incal.el > batch.el > bibtex-incal.el > bike.el > bmi.el > buc.el (✿╹◡╹) that does not seem to easy anything and it can be replaced with few lines. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 6:40 ` Jean Louis @ 2021-06-21 16:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 19:55 ` Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 16:31 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >> (let*((emacs-dir "~/.emacs.d") >> (lisp-dir (format "%s/lisp" emacs-dir)) >> (init-dir (format "%s/emacs-init" emacs-dir)) >> (erc-dir (format "%s/erc" init-dir)) >> (gnus-dir (format "%s/gnus" init-dir)) >> (ide-dir (format "%s/ide" init-dir)) >> (w3m-dir (format "%s/w3m" init-dir)) >> (dirs (list >> lisp-dir >> init-dir >> erc-dir >> gnus-dir >> ide-dir >> w3m-dir >> ))) >> (dolist (d dirs) >> (push d load-path) ) >> (let ((emacs-init-files '( >> abc.el >> align-incal.el >> batch.el >> bibtex-incal.el >> bike.el >> bmi.el >> buc.el > > that does not seem to easy anything and it can be replaced > with few lines. ? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 16:31 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 19:55 ` Jean Louis 2021-06-22 0:06 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-21 19:55 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-06-21 20:21]: > Jean Louis wrote: > > >> (let*((emacs-dir "~/.emacs.d") > >> (lisp-dir (format "%s/lisp" emacs-dir)) > >> (init-dir (format "%s/emacs-init" emacs-dir)) > >> (erc-dir (format "%s/erc" init-dir)) > >> (gnus-dir (format "%s/gnus" init-dir)) > >> (ide-dir (format "%s/ide" init-dir)) > >> (w3m-dir (format "%s/w3m" init-dir)) > >> (dirs (list > >> lisp-dir > >> init-dir > >> erc-dir > >> gnus-dir > >> ide-dir > >> w3m-dir > >> ))) > >> (dolist (d dirs) > >> (push d load-path) ) You could put all configuration directories under unified one, for example: ~/.emacs.d/my-config/lisp ~/.emacs.d/my-config/erc-dir ~/.emacs.d/my-config/gnus-dir etc. Then just do: (setq load-path (append load-path (delq nil (mapcar (lambda (f) (when (file-directory-p f) f)) (directory-files "/home/admin/.emacs.d/my-config" t))))) -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 19:55 ` Jean Louis @ 2021-06-22 0:06 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:06 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >>>> (let*((emacs-dir "~/.emacs.d") >>>> (lisp-dir (format "%s/lisp" emacs-dir)) >>>> (init-dir (format "%s/emacs-init" emacs-dir)) >>>> (erc-dir (format "%s/erc" init-dir)) >>>> (gnus-dir (format "%s/gnus" init-dir)) >>>> (ide-dir (format "%s/ide" init-dir)) >>>> (w3m-dir (format "%s/w3m" init-dir)) >>>> (dirs (list >>>> lisp-dir >>>> init-dir >>>> erc-dir >>>> gnus-dir >>>> ide-dir >>>> w3m-dir >>>> ))) >>>> (dolist (d dirs) >>>> (push d load-path) ) > > You could put all configuration directories under unified > one, for example: > > ~/.emacs.d/my-config/lisp > ~/.emacs.d/my-config/erc-dir > ~/.emacs.d/my-config/gnus-dir What are you talking about? > etc. > > Then just do: > > (setq load-path (append load-path (delq nil (mapcar (lambda > (f) (when (file-directory-p f) f)) > (directory-files > "/home/admin/.emacs.d/my-config" t))))) ? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 2:56 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 6:40 ` Jean Louis @ 2021-06-21 10:14 ` Arthur Miller 2021-06-21 16:40 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 11:29 ` Eli Zaretskii 2021-06-21 20:02 ` Jean Louis 3 siblings, 1 reply; 86+ messages in thread From: Arthur Miller @ 2021-06-21 10:14 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> writes: > Hongyi Zhao wrote: > >> I noticed the following instructions/tools for Emacs modular >> configuration: >> >> https://www.emacswiki.org/emacs/DotEmacsModular >> https://www.emacswiki.org/emacs/DotEmacsStructuring >> https://github.com/emacs-jp/init-loader >> >> There are so many ways to do this. What's the >> preferable way? > > My personal favorite is the method below, I don't know if > that's mentioned on any of your links. > > Note that every file is mentioned explicitly, that means if > you are to search for an error (say do the so-called binary > search) you don't have to comment in and out code that might > have comments, headers, footers, and so on, instead you just > comment out one or more filenames, and when the bug or > misfeature is localized, it is as easy to enable them again. > > (let*((emacs-dir "~/.emacs.d") > (lisp-dir (format "%s/lisp" emacs-dir)) > (init-dir (format "%s/emacs-init" emacs-dir)) > (erc-dir (format "%s/erc" init-dir)) > (gnus-dir (format "%s/gnus" init-dir)) > (ide-dir (format "%s/ide" init-dir)) > (w3m-dir (format "%s/w3m" init-dir)) Isn't it better to use path formatting function instead of string formatting to ensure platform indepent paths and such? Something like this: (let ((etc (expand-file-name "etc" user-emacs-directory))) (unless (file-directory-p etc) (make-directory etc)) (setq show-paren-style 'expression ..... backup-directory-alist `(("." . ,etc)) custom-file (expand-file-name "emacs-custom.el" etc) abbrev-file-name (expand-file-name "abbrevs.el" etc) bookmark-default-file (expand-file-name "bookmarks" etc))) https://github.com/amno1/.emacs.d/blob/main/init.org ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 10:14 ` Arthur Miller @ 2021-06-21 16:40 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:25 ` [External] : " Drew Adams 2021-06-21 18:38 ` Arthur Miller 0 siblings, 2 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 16:40 UTC (permalink / raw) To: help-gnu-emacs Arthur Miller wrote: > Isn't it better to use path formatting function instead of > string formatting to ensure platform indepent paths If the path is a string and the filename is a string joining them with "string formatting" is pretty natural I think? Or what do you think one should do to put together for example the complete path ~/.emacs.d/emacs-init/erc/erc-iterate.el ? That path (and the entire) file isn't platform independent to begin with and has never been used outside the Unix world BTW, but why not add that for fun if there is a way that is better... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Re: Emacs Modular Configuration: the preferable way. 2021-06-21 16:40 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 18:25 ` Drew Adams 2021-06-26 0:17 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:38 ` Arthur Miller 1 sibling, 1 reply; 86+ messages in thread From: Drew Adams @ 2021-06-21 18:25 UTC (permalink / raw) To: Emanuel Berg; +Cc: Help-Gnu-Emacs (help-gnu-emacs@gnu.org) > > Isn't it better to use path formatting function instead of > > string formatting to ensure platform indepent paths > > If the path is a string and the filename is a string joining > them with "string formatting" is pretty natural I think? > > Or what do you think one should do to put together for example > the complete path ~/.emacs.d/emacs-init/erc/erc-iterate.el ? Put together how? from what? https://www.gnu.org/software/emacs/manual/html_node/elisp/File-Names.html https://www.gnu.org/software/emacs/manual/html_node/elisp/File-Name-Components.html > That path (and the entire) file isn't platform independent to > begin with and has never been used outside the Unix world BTW, > but why not add that for fun if there is a way that is > better... Actually, ~/.emacs.d/emacs-init/erc/erc-iterate.el is completely _platform independent_ when used in Emacs. Emacs takes care of platform differences / oddities automatically. Automatically, that is, provided code uses Elisp file-name functions (or the predefined commands that use them)... Yes, this is one of the things that the file-name functions you seem so terrorized by do for you. And this is presumably why the OP specifically mentioned that for his own use he didn't need to worry about such differences. (Which is true, as far as it goes.) Is Emacs "outside the Unix world" because it does this for you? If so, so be it. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Re: Emacs Modular Configuration: the preferable way. 2021-06-21 18:25 ` [External] : " Drew Adams @ 2021-06-26 0:17 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 0:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 0:17 UTC (permalink / raw) To: help-gnu-emacs Drew Adams wrote: > Actually, ~/.emacs.d/emacs-init/erc/erc-iterate.el is > completely _platform independent_ when used in Emacs. > Emacs takes care of platform differences / > oddities automatically. > > Automatically, that is, provided code uses Elisp file-name > functions (or the predefined commands that use them)... But why don't put that in the functions where something can go wrong because they are the ones that should be responsible for that, using string functions on a string doesn't imply any danger whatsoever so if one wants to be safe that doesn't make it any more safe, because it is already safe. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Re: Emacs Modular Configuration: the preferable way. 2021-06-26 0:17 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 0:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 0:31 UTC (permalink / raw) To: help-gnu-emacs >> Actually, ~/.emacs.d/emacs-init/erc/erc-iterate.el is >> completely _platform independent_ when used in Emacs. >> Emacs takes care of platform differences / >> oddities automatically. >> >> Automatically, that is, provided code uses Elisp file-name >> functions (or the predefined commands that use them)... > > But why don't put that in the functions where something can > go wrong because they are the ones that should be > responsible for that, using string functions on a string > doesn't imply any danger whatsoever so if one wants to be > safe that doesn't make it any more safe, because it is > already safe. Let's take a more practical approach, you mention file-name, what I can see there are these function, some of them what they do one can understand, assume, or guess, but I don't understand 100% what one is supposed to do, send the path as one fancies it to a function and get the same thing back, only on some other system it is changed to work there? If so, what function is that? I still don't understand why this is done manually but it is just a detail, I'll enclose it if that's how it is supposed to look... file-name-absolute-p file-name-all-completions file-name-as-directory file-name-base file-name-case-insensitive-p file-name-completion file-name-directory file-name-extension file-name-non-special file-name-nondirectory file-name-quote file-name-quoted-p file-name-sans-extension file-name-sans-versions file-name-shadow-mode file-name-unquote -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 16:40 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:25 ` [External] : " Drew Adams @ 2021-06-21 18:38 ` Arthur Miller 2021-06-22 0:03 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 1 reply; 86+ messages in thread From: Arthur Miller @ 2021-06-21 18:38 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> writes: > Arthur Miller wrote: > >> Isn't it better to use path formatting function instead of >> string formatting to ensure platform indepent paths > > If the path is a string and the filename is a string joining > them with "string formatting" is pretty natural I think? In some functions it matters if you end filename with a slash or not when you work with directories. Path formatting functions take care of that for example. Personally I think it is less error prone, than using string functions. > Or what do you think one should do to put together for example > the complete path ~/.emacs.d/emacs-init/erc/erc-iterate.el ? I pasted you an example from my init file. > That path (and the entire) file isn't platform independent to > begin with and has never been used outside the Unix world BTW, > but why not add that for fun if there is a way that is > better... It is up to you how you write your init file, but they say never say never ... ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 18:38 ` Arthur Miller @ 2021-06-22 0:03 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:17 ` Jean Louis 2021-06-22 7:52 ` Arthur Miller 0 siblings, 2 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:03 UTC (permalink / raw) To: help-gnu-emacs > In some functions it matters if you end filename with > a slash or not when you work with directories. I can imagine the situation but if it should do different things depending on if it is a directory or a regular file, it is better for these functions themselves to determine what it is, and not rely on the user of the function to insert a slash to denote a directory... >> Or what do you think one should do to put together for >> example the complete path >> ~/.emacs.d/emacs-init/erc/erc-iterate.el ? > > I pasted you an example from my init file. All that can't possibly be less error prone than a simple string concat with `format', besides what errors exactly are we trying to avoid? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-22 0:03 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:17 ` Jean Louis 2021-06-22 7:52 ` Arthur Miller 1 sibling, 0 replies; 86+ messages in thread From: Jean Louis @ 2021-06-22 0:17 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-06-22 03:04]: > > In some functions it matters if you end filename with > > a slash or not when you work with directories. > > I can imagine the situation but if it should do different > things depending on if it is a directory or a regular file, it > is better for these functions themselves to determine what it > is, and not rely on the user of the function to insert a slash > to denote a directory... (setq file "") ⇒ "" (file-exists-p file) ⇒ t ;; this is funny to me, but I guess both ;; directory and file are files... (file-exists-p "/") ⇒ t ;; aha, directory is file too... Then: (expand-file-name file) ⇒ "/home/data1/protected/tmp" ;; aha, this one is ;; directory, ;; that is why ;; empty string ;; is considered ;; file. (file-name-as-directory "") ⇒ "./" ;; now it makes more sense and now we get it as directory with a slash: (file-name-as-directory (expand-file-name "")) ⇒ "/home/data1/protected/tmp/" (defun directory (file) (when (and (stringp file) (file-exists-p file)) (file-name-as-directory (expand-file-name file)))) (directory "") ⇒ "/home/data1/protected/tmp/" ;; because that is my current directory (directory "/home") ⇒ "/home/" If directory does not exist, return NIL: (directory "/home-is-not-here") ⇒ nil -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-22 0:03 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:17 ` Jean Louis @ 2021-06-22 7:52 ` Arthur Miller 2021-06-26 6:58 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 1 reply; 86+ messages in thread From: Arthur Miller @ 2021-06-22 7:52 UTC (permalink / raw) To: help-gnu-emacs Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> writes: >> In some functions it matters if you end filename with >> a slash or not when you work with directories. > > I can imagine the situation but if it should do different > things depending on if it is a directory or a regular file, it > is better for these functions themselves to determine what it > is, and not rely on the user of the function to insert a slash > to denote a directory... > >>> Or what do you think one should do to put together for >>> example the complete path >>> ~/.emacs.d/emacs-init/erc/erc-iterate.el ? >> >> I pasted you an example from my init file. > > All that can't possibly be less error prone than a simple > string concat with `format', besides what errors exactly are > we trying to avoid? "All that" was far less than what you had :). I do think it is less error prone. It lets me type less of long paths, then if I was typing and concating strings. As you see I have setup one directory, "etc", and everything is relative to that one. Instead of typing and concating every file name for every directory and file, I can use that parth as a variable. If i decide to change that directory I don't need to do it in 20 different places and re-type everything, I can just type it in one place. Even with search-replace I think it is more error prone to have it the way you do, than to have just one place to edit. For me it is important to be able to clone my setup from git and just generate init files without having to tweak much. Currently I am able to actually do that on both my stationary gnu/linux computer and a Windows laptop. Not hardcoding paths as you did is one part of that setup. Even if you personally don't care about other OS:s then *nix, you may still have different physical machines with slightly different setup, say some simple Pi computer and more powerful desktop computer which might have different capabilities and your Emacs init doing differnt things at startup, with different paths, hardware etc. I don't know, just how I am using my computer(s), you may of course setup your init file the way you prefer. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-22 7:52 ` Arthur Miller @ 2021-06-26 6:58 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 6:58 UTC (permalink / raw) To: help-gnu-emacs Arthur Miller wrote: >> All that can't possibly be less error prone than a simple >> string concat with `format', besides what errors exactly >> are we trying to avoid? > > "All that" was far less than what you had :). I do think it > is less error prone. > > It lets me type less of long paths, then if I was typing and > concating strings. As you see I have setup one directory, > "etc", and everything is relative to that one. Instead of > typing and concating every file name for every directory and > file, I can use that parth as a variable. If i decide to > change that directory I don't need to do it in 20 different > places and re-type everything, I can just type it in one > place. Even with search-replace I think it is more error > prone to have it the way you do, than to have just one place > to edit. ? I'm not retyping any paths either, that's the whole point (lisp-dir (format "%s/lisp" emacs-dir)) (init-dir (format "%s/emacs-init" emacs-dir)) (erc-dir (format "%s/erc" init-dir)) (gnus-dir (format "%s/gnus" init-dir)) (ide-dir (format "%s/ide" init-dir)) (w3m-dir (format "%s/w3m" init-dir)) I retype variable names of the variables that hold them but that's another thing, if I make a typo there Emacs should warn me somewhere along the way. And more than that, it is just a principle which is sound to always uphold not duplicate the same data. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 2:56 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 6:40 ` Jean Louis 2021-06-21 10:14 ` Arthur Miller @ 2021-06-21 11:29 ` Eli Zaretskii 2021-06-21 12:45 ` Philip Kaludercic 2021-06-21 20:02 ` Jean Louis 3 siblings, 1 reply; 86+ messages in thread From: Eli Zaretskii @ 2021-06-21 11:29 UTC (permalink / raw) To: help-gnu-emacs > Date: Mon, 21 Jun 2021 04:56:04 +0200 > From: Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> > > (let*((emacs-dir "~/.emacs.d") > (lisp-dir (format "%s/lisp" emacs-dir)) > (init-dir (format "%s/emacs-init" emacs-dir)) > (erc-dir (format "%s/erc" init-dir)) > (gnus-dir (format "%s/gnus" init-dir)) > (ide-dir (format "%s/ide" init-dir)) > (w3m-dir (format "%s/w3m" init-dir)) Why are you using 'format' where expand-file-name should be used? ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 11:29 ` Eli Zaretskii @ 2021-06-21 12:45 ` Philip Kaludercic 2021-06-21 12:55 ` Eli Zaretskii ` (3 more replies) 0 siblings, 4 replies; 86+ messages in thread From: Philip Kaludercic @ 2021-06-21 12:45 UTC (permalink / raw) To: Eli Zaretskii; +Cc: help-gnu-emacs Eli Zaretskii <eliz@gnu.org> writes: >> Date: Mon, 21 Jun 2021 04:56:04 +0200 >> From: Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> >> >> (let*((emacs-dir "~/.emacs.d") >> (lisp-dir (format "%s/lisp" emacs-dir)) >> (init-dir (format "%s/emacs-init" emacs-dir)) >> (erc-dir (format "%s/erc" init-dir)) >> (gnus-dir (format "%s/gnus" init-dir)) >> (ide-dir (format "%s/ide" init-dir)) >> (w3m-dir (format "%s/w3m" init-dir)) > > Why are you using 'format' where expand-file-name should be used? Does it really make a difference in a personal configuration, especially when you don't use Windows or other non /-delimiting systems? -- Philip K. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 12:45 ` Philip Kaludercic @ 2021-06-21 12:55 ` Eli Zaretskii 2021-06-21 13:59 ` [External] : " Drew Adams 2021-06-21 14:11 ` tomas ` (2 subsequent siblings) 3 siblings, 1 reply; 86+ messages in thread From: Eli Zaretskii @ 2021-06-21 12:55 UTC (permalink / raw) To: help-gnu-emacs > From: Philip Kaludercic <philipk@posteo.net> > Cc: help-gnu-emacs@gnu.org > Date: Mon, 21 Jun 2021 12:45:49 +0000 > > Eli Zaretskii <eliz@gnu.org> writes: > > >> Date: Mon, 21 Jun 2021 04:56:04 +0200 > >> From: Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> > >> > >> (let*((emacs-dir "~/.emacs.d") > >> (lisp-dir (format "%s/lisp" emacs-dir)) > >> (init-dir (format "%s/emacs-init" emacs-dir)) > >> (erc-dir (format "%s/erc" init-dir)) > >> (gnus-dir (format "%s/gnus" init-dir)) > >> (ide-dir (format "%s/ide" init-dir)) > >> (w3m-dir (format "%s/w3m" init-dir)) > > > > Why are you using 'format' where expand-file-name should be used? > > Does it really make a difference in a personal configuration, especially > when you don't use Windows or other non /-delimiting systems? (a) It's definitely slower; (b) it teaches you bad habits, which you are likely to apply even in non-personal cases; (c) this here is a public place where you affect others, not just your personal code on a known flavor of systems. ^ permalink raw reply [flat|nested] 86+ messages in thread
* RE: [External] : Re: Emacs Modular Configuration: the preferable way. 2021-06-21 12:55 ` Eli Zaretskii @ 2021-06-21 13:59 ` Drew Adams 2021-06-21 16:51 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Drew Adams @ 2021-06-21 13:59 UTC (permalink / raw) To: Eli Zaretskii, help-gnu-emacs@gnu.org > > > Why are you using 'format' where expand-file-name should be used? > > > > Does it really make a difference in a personal configuration, especially > > when you don't use Windows or other non /-delimiting systems? > > (a) It's definitely slower; (b) it teaches you bad habits, which you > are likely to apply even in non-personal cases; (c) this here is a > public place where you affect others, not just your personal code on a > known flavor of systems. +1. It's common for those new to Elisp to look for, find, and use string-manipulation functions to manipulate file names and their components. Unfortunately (but understandably). Those things are not just strings - they're strings with particular meaning and behavior. Which is why Elisp has particular functions to support them. Just-strings naivete is hard enough to guide folks around (away from), without help sites such as this reinforcing it, however inadvertently. Guidance and discussion here that prevents or corrects such misunderstanding is helpful. Once pointed to things like `expand-file-name', it behooves you to use them. You won't regret it, and doing so will help others by passing along the tip. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Re: Emacs Modular Configuration: the preferable way. 2021-06-21 13:59 ` [External] : " Drew Adams @ 2021-06-21 16:51 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:08 ` Eli Zaretskii 2021-06-21 18:26 ` FW: " Drew Adams 0 siblings, 2 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 16:51 UTC (permalink / raw) To: help-gnu-emacs Drew Adams wrote: > It's common for those new to Elisp to look for, find, and > use string-manipulation functions to manipulate file names > and their components. Unfortunately (but understandably). Why are filenames strings then? Make a new type for them if you don't like one to use and modify them as strings. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: [External] : Re: Emacs Modular Configuration: the preferable way. 2021-06-21 16:51 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 18:08 ` Eli Zaretskii 2021-06-21 18:26 ` FW: " Drew Adams 1 sibling, 0 replies; 86+ messages in thread From: Eli Zaretskii @ 2021-06-21 18:08 UTC (permalink / raw) To: Emanuel Berg; +Cc: help-gnu-emacs > Date: Mon, 21 Jun 2021 18:51:38 +0200 > From: Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> > > Drew Adams wrote: > > > It's common for those new to Elisp to look for, find, and > > use string-manipulation functions to manipulate file names > > and their components. Unfortunately (but understandably). > > Why are filenames strings then? They aren't. We represent file names as strings, but they aren't _just_ strings. In a way analogous to characters, which are not _just_ integers. ^ permalink raw reply [flat|nested] 86+ messages in thread
* FW: [External] : Re: Emacs Modular Configuration: the preferable way. 2021-06-21 16:51 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:08 ` Eli Zaretskii @ 2021-06-21 18:26 ` Drew Adams 2021-06-26 0:06 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 1 reply; 86+ messages in thread From: Drew Adams @ 2021-06-21 18:26 UTC (permalink / raw) To: Emanuel Berg, Help-Gnu-Emacs (help-gnu-emacs@gnu.org) > > It's common for those new to Elisp to look for, find, and > > use string-manipulation functions to manipulate file names > > and their components. Unfortunately (but understandably). > > Why are filenames strings then? A file name is a string. A string is not necessarily a file name. > Make a new type for them if you don't like one to use > and modify them as strings. I don't care whether you use and modify file-name strings as arbitrary strings. Feel free to do that. My advice was for anyone who's open to it. It will generally help people to use the file-name functions, in my experience. You can likely find stories of problems users have run into by not doing so. YMMV. Anyone (including you) can submit an enhancement request (`M-x report-emacs-bug') to do <whatever>, including to add a file-name type. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: FW: [External] : Re: Emacs Modular Configuration: the preferable way. 2021-06-21 18:26 ` FW: " Drew Adams @ 2021-06-26 0:06 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 0:06 UTC (permalink / raw) To: help-gnu-emacs Drew Adams wrote: > Anyone (including you) can submit an enhancement request > (`M-x report-emacs-bug') to do <whatever>, including to add > a file-name type. Hah, I don't think one should do that, I think the functions that are sensitive to, in your words, <whatever>, should - and only at that point - verify their inputs - and not rely on the user to do that way before and there is no saying what will happen after that and in between. If several functions have this sensitivity to people string manipulating the string indata, maybe they can share a function to sanitize it - I mean, wouldn't that make it modular, even? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 12:45 ` Philip Kaludercic 2021-06-21 12:55 ` Eli Zaretskii @ 2021-06-21 14:11 ` tomas 2021-06-21 16:47 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 20:36 ` Emacs Modular Configuration: the preferable way Jean Louis 2021-06-21 16:42 ` Emacs Modular Configuration: the preferable way Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 12:50 ` Lars Ingebrigtsen 3 siblings, 2 replies; 86+ messages in thread From: tomas @ 2021-06-21 14:11 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 888 bytes --] On Mon, Jun 21, 2021 at 12:45:49PM +0000, Philip Kaludercic wrote: > Eli Zaretskii <eliz@gnu.org> writes: [...] > > Why are you using 'format' where expand-file-name should be used? > > Does it really make a difference in a personal configuration, especially > when you don't use Windows or other non /-delimiting systems? Of course, the OP can do what (s)he wants at home, but once the code ends up in public, as above, such a hint as Eli's is invaluable. If you want to see what happens otherwise, have a look at PHP. The language itself has evolved a lot since its beginnings (to the better, IMO). But you still see extremely bad habits "out there" which wouldn't be necessary these days -- because, well, they are "out there" (for example: assebling SQL queries with sprintf [1]). They take a life of their own :-) Cheers [1] https://xkcd.com/327/ - t [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 14:11 ` tomas @ 2021-06-21 16:47 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:06 ` Eli Zaretskii ` (2 more replies) 2021-06-21 20:36 ` Emacs Modular Configuration: the preferable way Jean Louis 1 sibling, 3 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 16:47 UTC (permalink / raw) To: help-gnu-emacs tomas wrote: > Of course, the OP can do what (s)he wants at home, but once > the code ends up in public, as above, such a hint as Eli's > is invaluable. It stinks. > If you want to see what happens otherwise, have a look > at PHP. > > The language itself has evolved a lot since its beginnings > (to the better, IMO). But you still see extremely bad habits > "out there" which wouldn't be necessary these days -- > because, well, they are "out there" (for example: assebling > SQL queries with sprintf [1]). They take a life of their own > :-) If it is string to begin with and the end result is a string one should be able to use string functions to "assemble" it. It is just as natural as using addition and subtraction with integers. Read the book on type theory if you don't believe me! And the Wikipedia page on type systems. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 16:47 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 18:06 ` Eli Zaretskii 2021-06-21 21:09 ` Jean Louis 2021-06-21 20:05 ` Stefan Monnier via Users list for the GNU Emacs text editor 2021-06-21 21:07 ` Jean Louis 2 siblings, 1 reply; 86+ messages in thread From: Eli Zaretskii @ 2021-06-21 18:06 UTC (permalink / raw) To: help-gnu-emacs > Date: Mon, 21 Jun 2021 18:47:17 +0200 > From: Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> > > If it is string to begin with and the end result is a string > one should be able to use string functions to "assemble" it. Repeat after me: "filenames are not strings", "filenames are not strings", "filenames... Bonus points for coming up with at least one use case which shows how filenames are not just strings. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 18:06 ` Eli Zaretskii @ 2021-06-21 21:09 ` Jean Louis 2021-06-22 11:45 ` Eli Zaretskii 0 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-21 21:09 UTC (permalink / raw) To: Eli Zaretskii; +Cc: help-gnu-emacs * Eli Zaretskii <eliz@gnu.org> [2021-06-21 21:07]: > > Date: Mon, 21 Jun 2021 18:47:17 +0200 > > From: Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> > > > > If it is string to begin with and the end result is a string > > one should be able to use string functions to "assemble" it. > > Repeat after me: "filenames are not strings", "filenames are not > strings", "filenames... > > Bonus points for coming up with at least one use case which shows how > filenames are not just strings. As an irrelevant side note, this one bothers me: (file-exists-p "") ⇒ t Is that supposed to be so? ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 21:09 ` Jean Louis @ 2021-06-22 11:45 ` Eli Zaretskii 2021-06-22 12:29 ` Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Eli Zaretskii @ 2021-06-22 11:45 UTC (permalink / raw) To: help-gnu-emacs > Date: Tue, 22 Jun 2021 00:09:40 +0300 > From: Jean Louis <bugs@gnu.support> > Cc: help-gnu-emacs@gnu.org > > As an irrelevant side note, this one bothers me: > > (file-exists-p "") ⇒ t > > Is that supposed to be so? Yes, there are good practical reasons for this behavior. Repeat after me: "file names are not just strings"... ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-22 11:45 ` Eli Zaretskii @ 2021-06-22 12:29 ` Jean Louis 2021-06-22 13:07 ` Eli Zaretskii 0 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-22 12:29 UTC (permalink / raw) To: Eli Zaretskii; +Cc: help-gnu-emacs * Eli Zaretskii <eliz@gnu.org> [2021-06-22 14:46]: > > Date: Tue, 22 Jun 2021 00:09:40 +0300 > > From: Jean Louis <bugs@gnu.support> > > Cc: help-gnu-emacs@gnu.org > > > > As an irrelevant side note, this one bothers me: > > > > (file-exists-p "") ⇒ t > > > > Is that supposed to be so? > > Yes, there are good practical reasons for this behavior. > > Repeat after me: "file names are not just strings"... I understand that "" is meant to represent ./ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-22 12:29 ` Jean Louis @ 2021-06-22 13:07 ` Eli Zaretskii 0 siblings, 0 replies; 86+ messages in thread From: Eli Zaretskii @ 2021-06-22 13:07 UTC (permalink / raw) To: help-gnu-emacs > Date: Tue, 22 Jun 2021 15:29:38 +0300 > From: Jean Louis <bugs@gnu.support> > Cc: help-gnu-emacs@gnu.org > > * Eli Zaretskii <eliz@gnu.org> [2021-06-22 14:46]: > > > Date: Tue, 22 Jun 2021 00:09:40 +0300 > > > From: Jean Louis <bugs@gnu.support> > > > Cc: help-gnu-emacs@gnu.org > > > > > > As an irrelevant side note, this one bothers me: > > > > > > (file-exists-p "") ⇒ t > > > > > > Is that supposed to be so? > > > > Yes, there are good practical reasons for this behavior. > > > > Repeat after me: "file names are not just strings"... > > I understand that "" is meant to represent ./ Yes, that's true. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 16:47 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:06 ` Eli Zaretskii @ 2021-06-21 20:05 ` Stefan Monnier via Users list for the GNU Emacs text editor 2021-06-22 0:16 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 21:07 ` Jean Louis 2 siblings, 1 reply; 86+ messages in thread From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2021-06-21 20:05 UTC (permalink / raw) To: help-gnu-emacs > If it is string to begin with and the end result is a string > one should be able to use string functions to "assemble" it. Yet `lisp/emacs-lisp/bytecomp.el` doesn't use this strategy in order to transform the string found in `foo.el` into the string we want in `foo.elc`. Stefan ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 20:05 ` Stefan Monnier via Users list for the GNU Emacs text editor @ 2021-06-22 0:16 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:16 UTC (permalink / raw) To: help-gnu-emacs Stefan Monnier via Users list for the GNU Emacs text editor wrote: >> If it is string to begin with and the end result is >> a string one should be able to use string functions to >> "assemble" it. > > Yet `lisp/emacs-lisp/bytecomp.el` doesn't use this strategy > in order to transform the string found in `foo.el` into the > string we want in `foo.elc`. It doesn't? ~/src/emacs-28.0.50/lisp/emacs-lisp/bytecomp.el lines 182-186: (setq filename (file-name-sans-versions (byte-compiler-base-file-name filename))) (cond ((string-match emacs-lisp-file-regexp filename) (concat (substring filename 0 (match-beginning 0)) ".elc")) (t (concat filename ".elc"))))) -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 16:47 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:06 ` Eli Zaretskii 2021-06-21 20:05 ` Stefan Monnier via Users list for the GNU Emacs text editor @ 2021-06-21 21:07 ` Jean Louis 2021-06-22 0:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-21 21:07 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-06-21 20:07]: > > The language itself has evolved a lot since its beginnings > > (to the better, IMO). But you still see extremely bad habits > > "out there" which wouldn't be necessary these days -- > > because, well, they are "out there" (for example: assebling > > SQL queries with sprintf [1]). They take a life of their own > > :-) > > If it is string to begin with and the end result is a string > one should be able to use string functions to "assemble" it. I am thinking how can I make it safer for SQL queries. It seem not an easy task. Major updating function is using this: (let* ((table "new") (column "new_name") (new-value "'Joe'") (id 1) (sql (format "UPDATE %s SET %s = %s WHERE %s_id = %s RETURNING %s_id" table column new-value table id table))) (message sql) (rcd-sql-first sql db)) ⇒ 1 Then I have to convert it to following by its meaning: (let* ((table "new") (column "new_name") (new-value "'Joe'") (id 1) (parameters (list table column new-value id)) (sql "UPDATE $1 SET $2 = $3 WHERE $1_id = $4 RETURNING $1_id")) (message sql) (rcd-sql-first sql db parameters)) But no, that does not work: if: Wrong type argument: stringp, ("ERROR: syntax error at or near \"$1\" LINE 1: UPDATE $1 SET $2 = $3 WHERE $1_id = $4 RETURNING $1_id ^ " "42601") As those paramters are probably converted to strings. Thus I cannot avoid using the function `format' just everywhere, but I can minimize it wherever there is possible danger for SQL injection (though this below is not working): (let* ((table "new") (column "new_name") (new-value "'Joe'") (id 1) (parameters (list new-value id)) (sql (format "UPDATE %s SET %s = $1 WHERE %s_id = $2 RETURNING %s_id" table column table table))) (message sql) (rcd-sql-first sql db parameters)) Maybe solution would be to use `format' in steps, so that final step can accept users' input. Issue is not solved. First I have to contact developers of `emacs-libpq' package to see if this is error, as it returns string by supplying integer parameter: This is not expected: (pq:query db "SELECT $1" 100) ⇒ ("100") While this is expected: (pq:query db "SELECT $1" "100") ⇒ ("100") So the issue is pending on Github: https://github.com/anse1/emacs-libpq/issues/19 -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 21:07 ` Jean Louis @ 2021-06-22 0:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:52 ` Printf and quoting in general, SQL injection in particular Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:33 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >>> The language itself has evolved a lot since its beginnings >>> (to the better, IMO). But you still see extremely bad >>> habits "out there" which wouldn't be necessary these days >>> -- because, well, they are "out there" (for example: >>> assebling SQL queries with sprintf [1]). They take a life >>> of their own :-) >> >> If it is string to begin with and the end result is >> a string one should be able to use string functions to >> "assemble" it. > > I am thinking how can I make it safer for SQL queries. SQL injection isn't avoided by not assembling queries with string functions but by quoting user input. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular 2021-06-22 0:33 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:52 ` Jean Louis 2021-06-26 6:50 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-22 0:52 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-06-22 03:35]: > > I am thinking how can I make it safer for SQL queries. > > SQL injection isn't avoided by not assembling queries with > string functions but by quoting user input. It is impossible in `emacs-libpq' package to avoid formatting strings and passing it to database. What is possible is to minimize it so that users' input is automatically quoted by the database by passing it as parameters instead of passing data as parameters to `format'. I prefer the latter. There is less code. I have improved after Thomas's suggestions. Now I am preparings statements: (defun rcd-db-prepare-statement (name prepared pg) (unless (rcd-sql-first "SELECT statement FROM pg_prepared_statements WHERE name = $1" pg name) (rcd-sql prepared pg))) (defun rcd-db-prepare-statements () (rcd-db-prepare-statement "persons_emails" "PREPARE persons_emails(int) AS SELECT DISTINCT unnest(array[people_email1, people_email2, people_email3] || people_emailsobsolete) FROM people WHERE people_id = $1")) Now function is small and nice: (defun cf-emails-by-id (id) "Returns list of emails for contact ID" (delq nil (pq:query cf-db (format "EXECUTE persons_emails(%s)" id)))) and it was this big and without true necessity complex: (defun cf-emails-by-id (id) "Returns list of emails for contact ID" (let* ((sql (format "SELECT people_email1, people_email2, people_email3 FROM people WHERE people_id = %s" id)) (emails (rcd-sql-first sql cf-db)) (obsolete-emails (rcd-db-array-value-as-list "people" "people_emailsobsolete" id cf-db)) (emails (append emails obsolete-emails)) (emails (seq-remove 'seq-empty-p emails)) (emails (mapcar (lambda (e) (when (string-match "@" e) e)) emails)) (emails (remove nil emails))) emails)) -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular 2021-06-22 0:52 ` Printf and quoting in general, SQL injection in particular Jean Louis @ 2021-06-26 6:50 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 7:30 ` Yuri Khan 2021-06-28 7:02 ` Jean Louis 0 siblings, 2 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 6:50 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >>> I am thinking how can I make it safer for SQL queries. >> >> SQL injection isn't avoided by not assembling queries with >> string functions but by quoting user input. > > It is impossible in `emacs-libpq' package to avoid > formatting strings and passing it to database. > > What is possible is to minimize it so that users' input is > automatically quoted by the database by passing it as > parameters instead of passing data as parameters to `format' > [...] Relax, this notion that you shouldn't construct file paths by string functions, nor SQL queries for that matter, and what more? hyperlinks? or are you allowed to do that? These opinions are "arguably" correct at best - and that means some people will insist (argue) they are. And maybe that's what's happening right now? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular 2021-06-26 6:50 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 7:30 ` Yuri Khan 2021-06-26 7:57 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 9:37 ` tomas 2021-06-28 7:02 ` Jean Louis 1 sibling, 2 replies; 86+ messages in thread From: Yuri Khan @ 2021-06-26 7:30 UTC (permalink / raw) To: Emanuel Berg, help-gnu-emacs On Sat, 26 Jun 2021 at 13:56, Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> wrote: > Relax, this notion that you shouldn't construct file paths by > string functions, nor SQL queries for that matter, and what > more? hyperlinks? Hyperlinks, too. One of the requirements of URLs is that all non-ascii and some ascii characters be %-encoded when used in the path or query string, or punycode-encoded when used in the host name: (let ((base "http://ru.wikipedia.org/wiki/") (term "Гиперссылка") (joined (concat base term))) (assert (string= joined "https://ru.wikipedia.org/wiki/%D0%93%D0%B8%D0%BF%D0%B5%D1%80%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B0"))) ;; alas, no Another rule is that resolving a relative reference containing a path against a base URL will drop the last segment of the base: (let ((base "http://example.org/foo") (href "bar") (resolved (concat base href))) (assert (string= resolved "http://example.org/bar"))) ;; also no String concat does not know any of these rules. It is okay to represent file names, SQL queries, and URLs as strings *internally*. It is okay to use string functions to implement high-level domain-specific functions. In many cases, interoperating with external code will also require these things represented as strings. But it is a good idea to use domain-specific functions to manipulate file names, queries, and URLs, rather than string functions, because this way you are less likely to violate those types’ invariants. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular 2021-06-26 7:30 ` Yuri Khan @ 2021-06-26 7:57 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 9:37 ` tomas 1 sibling, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 7:57 UTC (permalink / raw) To: help-gnu-emacs Yuri Khan wrote: >> Relax, this notion that you shouldn't construct file paths >> by string functions, nor SQL queries for that matter, and >> what more? hyperlinks? > > Hyperlinks, too. > > One of the requirements of URLs is that all non-ascii and > some ascii characters be %-encoded when used in the path or > query string, or punycode-encoded when used in the host > name: > > (let ((base "http://ru.wikipedia.org/wiki/") > (term "Гиперссылка") > (joined (concat base term))) > (assert (string= joined > "https://ru.wikipedia.org/wiki/%D0%93%D0%B8%D0%BF%D0%B5%D1%80%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B0"))) > ;; alas, no > > Another rule is that resolving a relative reference > containing a path against a base URL will drop the last > segment of the base: > > (let ((base "http://example.org/foo") > (href "bar") > (resolved (concat base href))) > (assert (string= resolved "http://example.org/bar"))) ;; also no > > String concat does not know any of these rules. > > It is okay to represent file names, SQL queries, and URLs as > strings *internally*. It is okay to use string functions to > implement high-level domain-specific functions. In many > cases, interoperating with external code will also require > these things represented as strings. But it is a good idea > to use domain-specific functions to manipulate file names, > queries, and URLs, rather than string functions, because > this way you are less likely to violate those > types’ invariants. Interesting, what about typing? Not as error prone, because you see the result? So it is like a three stage hierarchy or procedure rather, 1. typing (just type, you see it anyway) 2. manipulate (domain-specific functions) 3. use (For hyperlinks, step 1 could be done with a lot of functions (protocol (domain (path (page (page-type ...) ? That'd just be grotesque. I don't know if that'd be more safe, really?) But OK, so instead of "anything goes, then verify input at step 3" - which is where it matters BTW - the approach is _type carefully_, then just exclusively use domain-specific manipulators. So all you have to care about is the typing part, because after that, it won't get messed up! I see the point, but - to be honest, string manipulation at this very basic level - and typing - I don't know, I feel kind of comfortable doing BOTH by now :) But never say never... I still don't understand what to replace my stuff with tho, (let*((emacs-dir "~/.emacs.d") (lisp-dir (format "%s/lisp" emacs-dir)) (init-dir (format "%s/emacs-init" emacs-dir)) (erc-dir (format "%s/erc" init-dir)) (gnus-dir (format "%s/gnus" init-dir)) (ide-dir (format "%s/ide" init-dir)) (w3m-dir (format "%s/w3m" init-dir)) (dirs (list lisp-dir init-dir erc-dir gnus-dir ide-dir w3m-dir ))) ... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular 2021-06-26 7:30 ` Yuri Khan 2021-06-26 7:57 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 9:37 ` tomas 1 sibling, 0 replies; 86+ messages in thread From: tomas @ 2021-06-26 9:37 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 945 bytes --] On Sat, Jun 26, 2021 at 02:30:59PM +0700, Yuri Khan wrote: > On Sat, 26 Jun 2021 at 13:56, Emanuel Berg via Users list for the GNU > Emacs text editor <help-gnu-emacs@gnu.org> wrote: > > > Relax, this notion that you shouldn't construct file paths by > > string functions, nor SQL queries for that matter, and what > > more? hyperlinks? > > Hyperlinks, too. Mmm. Yummy hyperlinks. You just have to enter "URL parsing injection" to enjoy a colourful bestiary. This is user-provided stuff which is parsed server-side. Creativity! Two nice links (of... thousands?) https://s1gnalcha0s.github.io/node/2015/01/31/SSJS-webshell-injection.html https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf I'm all for DIY, but in this case, it comes with one caveat. Know your stuff. Read. Have good data models. Read. Test. Read. Have fun - t [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular 2021-06-26 6:50 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 7:30 ` Yuri Khan @ 2021-06-28 7:02 ` Jean Louis 2021-07-06 2:12 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-28 7:02 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg <moasenwood@zoho.eu> [2021-06-26 02:55]: > Relax, this notion that you shouldn't construct file paths by > string functions, nor SQL queries for that matter, and what > more? hyperlinks? or are you allowed to do that? > > These opinions are "arguably" correct at best - and that means > some people will insist (argue) they are. And maybe that's > what's happening right now? We can observe the phenomena of raised warnings for various particular issues in programming. I am very fine with warnings and learn out of it. What I don't agree easily is sometimes how those warnings are formulated as there is usually deeper truthful meaning that could not express by poster clearly in the email. Sometimes warnings are in a wrong context. Whatever it may be, one thing is sure, there must be some truth there as warnings are given by experienced people. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular 2021-06-28 7:02 ` Jean Louis @ 2021-07-06 2:12 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-07-06 2:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 2:12 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: > Whatever it may be, one thing is sure, there must be some > truth there as warnings are given by experienced people. There is the Windows compatibility issue, that I accept. As for extra security in general that should be put in manually and in-between when what happens is as undramatic as a manipulation of a string - ha! - i.e., something that is 100% safe - I'm not convinced that actually adds security ... Maybe a false sense of security :P Maybe the functions are useful for other things as well tho, that's another thing, if so. Don't know what functions this refers to specifically, please provide a list for paths and URLs and I'll check my material... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular 2021-07-06 2:12 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 2:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 2:46 UTC (permalink / raw) To: help-gnu-emacs You guys spoke of symbols the other day and if they were mutable or not. Maybe here we have a use case... for, uhm, symbols! Maybe one can do this like this with properties, tag strings that are intended for or already paths and URLs, and they can only be used by safe functions! That I'd like more because that would imply a higher degree of automation, perhaps, but if nothing else the policy would be enforced, done deal. So when you sent an ordinary string to the file opener - ¡No pasarán! ha :) Compare (defun what-face (pos) (interactive "d") (let ((face (or (get-char-property pos 'face) (get-char-property pos 'read-cf-name) ))) (message "face: %s" (or face "no face")) )) or (defun gnus-article-show-filled-citation () "Fill the citation opened on a hidden-citation button press." (interactive) (let*((pos (point)) (button (get-char-property pos 'button)) ) (when button (widget-button-press pos) (save-excursion (gnus-article-fill-cited-article) )))) ;; source: ;; https://dataswamp.org/~incal/emacs-init/face.el ;; https://dataswamp.org/~incal/emacs-init/gnus/article.el -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 14:11 ` tomas 2021-06-21 16:47 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 20:36 ` Jean Louis 2021-06-21 21:15 ` Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] tomas 1 sibling, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-21 20:36 UTC (permalink / raw) To: tomas; +Cc: help-gnu-emacs * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-21 17:12]: > But you still see extremely bad habits "out there" which wouldn't be > necessary these days -- because, well, they are "out there" (for > example: assebling SQL queries with sprintf [1]). They take a life > of their own :-) > > Cheers > [1] https://xkcd.com/327/ Your small reference is definitely a possible danger if SQL input is anyhow exposed to public input. Within a close group or within a team the danger mentioned on the funny comic is practically non-existent as it will never take place on my side. It is highly unlikely to take place within third party Emacs Lisp collection of programs which are so much single user oriented. But then again, we never know it, and it is a bad habit. I am heavy user of the Emacs package: emacs-libpq @ Github https://github.com/anse1/emacs-libpq Your comment is important. ━━━━━━━━━━━━━━━━━━━━━━━━━━ I just guess that the package's original command: `pq:query' is so much safer than what I re-wrote: (defun rcd-sql (sql pg) "Sends SQL queries to PostgreSQL database and return results. Argument PG is database handle." (prog1 (condition-case err (pq:query pg sql) (error (if (string-match "^ERROR: syntax error" (cdr err)) (progn (if (fboundp 'speak) (speak (cdr err))) (message (cdr err))) ;; re-throw (signal (car err) (cdr err))))) (when rcd-db-sql-logging (funcall rcd-db-sql-message-function (string-replace "\n" " " sql))))) Thus I guess I would need to skip in some functions usage of function `format' and rather use the `pq:query' parameters: Then function should begin with: (defun rcd-sql (sql pg &rest parameters) "Sends SQL queries to PostgreSQL database and return results. Argument PG is database handle." (prog1 (condition-case err (apply 'pq:query pg sql parameters) (setq db (rcd-db-connect "admin")) db ⇒ #<user-ptr ptr=0x56037dece650 finalizer=0x7fafbd3dabb6> Then for the following, where both tables `data` and `data1' exist: (rcd-sql-first (format "INSERT INTO data (data_name) VALUES (%s) RETURNING data_id" (sql-escape-string "John")) db) ⇒ 16 as ID Attempt to ruin the table did not really work as there is error, and I don't know how to drop it maliciously. If you have idea let me know. (rcd-sql-first (format "INSERT INTO data (data_name) VALUES (%s)" "'John'); DROP TABLE data1;") db) But the idea is to use the arguments as they are automatically quoted by `pq:query' and I just hope there is some more "protection": (defun rcd-sql (sql pg &rest parameters) "Sends SQL queries to PostgreSQL database and return results. Argument PG is database handle." (prog1 (condition-case err (apply 'pq:query pg sql parameters) (error (if (string-match "^ERROR: syntax error" (cdr err)) (progn (if (fboundp 'speak) (speak (cdr err))) (message (cdr err))) ;; re-throw (signal (car err) (cdr err))))) (when rcd-db-sql-logging (funcall rcd-db-sql-message-function (string-replace "\n" " " sql))))) That it works preliminary: (rcd-sql "SELECT 1" db) ⇒ (1) And now with parameters, I see I am getting a string which was meant to be integer, this may be bug in the package: (rcd-sql "SELECT $1" db 1) ⇒ ("1") But then I can cast it to integer: (rcd-sql "SELECT $1::integer" db 1) ⇒ (1) Now again the attempt to drop the table: (rcd-sql "SELECT $1::integer" db "1; DROP TABLE data1;") - invalid input syntax New attempt, it did not work: (rcd-sql "SELECT $1" db "1; DROP TABLE data1;") ⇒ ("1; DROP TABLE data1;") Let us try with function `format' instead: ⛳ ⛳ ⛳ ⛳ ⛳ (rcd-sql (format "SELECT %s" "1; DROP TABLE data1;") db) ⇒ nil Bingo! This worked well. Let me try to destroy it by using parameters, again: (rcd-sql "SELECT $1" db "1; DROP TABLE data1;") ⇒ ("1; DROP TABLE data1;") That gives me only 249 `format' issues to verify and sanitize in a major file and probably about 200 other functions. Not that I was not thinking about this, I was thinking and I knew it is waiting for me. But I did not ackle it. Now when you mentioned it I feel I have to do it and use the parameters to the C function exposed in Emacs Lisp instead of the function `format'. 249 matches for "(sql (format" in buffer: rcd-cf.el 222: (let* ((sql (format "INSERT INTO people (people_firstname, people_middlenames, people_lastname, people_email1, people_account1, people_description) VALUES (%s, %s, %s, '%s', %s, '%s')" first-name middle-names last-name email account description))) 229: (sql (format "SELECT a.attname, 378: (let* ((sql (format "SELECT people_email1, people_email2, people_email3 FROM people WHERE people_id = %s" id)) 525: (sql (format "SELECT get_full_contacts_name(%s) FROM people WHERE people_id = %s" id id)) 549: (let* ((sql (format "SELECT people_id FROM people WHERE people_email1 ILIKE '%s' OR people_email2 ILIKE '%s' OR people_email3 ILIKE '%s' OR '%s' = ANY (people_emailsobsolete)" email email email email)) 562: (let* ((sql (format "SELECT people_id FROM people WHERE people_email1 ILIKE '%s' OR people_email2 ILIKE '%s' OR people_email3 ILIKE '%s' OR '%s' = ANY (people_emailsobsolete)" email email email email))) 568: (sql (format "SELECT people_id FROM people WHERE people_officephone ~ '%s' OR people_mobilephone ~ '%s' OR people_homephone ~ '%s' OR people_otherphone ~ '%s' OR people_fax ~ '%s' OR '%s' = ANY (people_phoneobsolete)" number number number number number original-number)) 579: (let ((sql (format "INSERT INTO contacts (people_lastname, people_mobilephone) VALUES (%s, %s) RETURNING people_id" (sql-escape-string number) (sql-escape-string number)))) 622: (let ((sql (format "SELECT people_id FROM people WHERE (people_account1 = %s OR people_account2 = %s OR people_account3 = %s) AND %s ~* %s ORDER BY people_id" account account account column (sql-escape-string query)))) 661: (let ((sql (format "SELECT count(notes_id) FROM notes WHERE notes_contact = %s" id))) 665: (let ((sql (format "SELECT count(markassignments_id) FROM markassignments WHERE markassignments_contact = %s" id))) 669: (let ((sql (format "SELECT count(1) FROM hyobjects WHERE hyobjects_people = %s OR hyobjects_assignedperson = %s" id id))) 673: (let ((sql (format "SELECT count(people_id) FROM people WHERE people_introducedby = %s" id))) 677: (let ((sql (format "SELECT count(calls_id) FROM calls WHERE calls_contact = %s" id))) 681: (let ((sql (format "SELECT count(sms_id) FROM sms WHERE sms_contacts = %s" id))) 711: (sql (format "INSERT INTO interactions (interactions_contacts, interactions_interactiontypes, interactions_count) VALUES (%s, %s, %s) ON CONFLICT (interactions_contacts,interactions_interactiontypes) DO UPDATE SET interactions_count = %s WHERE interactions.interactions_contacts = %s AND interactions.interactions_interactiontypes = %s;" id type count count id type))) 760: (let* ((sql (format "SELECT DISTINCT people_id as id FROM 814: (let* ((sql (format "SELECT tags_name FROM peopletags, tags WHERE tags_id = peopletags_tags AND peopletags_%s = %s" table id)) 820: (let ((sql (format "INSERT INTO peopletags (peopletags_%s, peopletags_tags) VALUES (%d, %d) ON CONFLICT (peopletags_%s, peopletags_tags) DO NOTHING RETURNING peopletags_id " table id tag table))) 935: (let ((sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(people_account1),'UNKNOWN') FROM people WHERE people_id IN (%s) ORDER BY people_id" (rcd-sql-id-list list)))) 996: (let* ((sql (format "SELECT CASE WHEN people_invalid1 IS NOT TRUE AND people_email1 ~ '@' THEN people_email1 WHEN people_invalid2 IS NOT TRUE AND people_email2 ~ '@' THEN people_email2 WHEN people_invalid3 IS NOT TRUE AND people_email3 ~ '@' THEN people_email3 ELSE NULL END AS email FROM people WHERE people_id = %s ORDER BY people_id LIMIT 1" contact))) 1008: (let* ((sql (format "SELECT CASE WHEN people_invalid1 IS NOT TRUE AND people_email1 ~ '@' THEN people_email1 ELSE NULL END AS email1, CASE WHEN people_invalid2 IS NOT TRUE AND people_email2 ~ '@' THEN people_email2 ELSE NULL END AS email2, CASE WHEN people_invalid3 IS NOT TRUE AND people_email3 ~ '@' THEN people_email3 ELSE NULL END AS email FROM people WHERE people_id = %s ORDER BY people_id LIMIT 1" contact))) 1013: (let* ((sql (format "SELECT people_officephone, people_mobilephone, people_homephone, people_otherphone, people_fax FROM people WHERE people_id = %s" contact))) 1056: (sql (format "INSERT INTO sms (sms_contacts, sms_smsstatus, sms_body, sms_phone) VALUES (%s, %s, %s, '%s') RETURNING sms_id" contact status (sql-escape-string body) phone))) 1061: (let* ((sql (format "SELECT sms_datecreated, sms_body, sms_phone FROM sms WHERE sms_datecreated = '%s' AND sms_body = %s" date (sql-escape-string text))) 1071: (let ((sql (format "INSERT INTO sms (sms_datecreated, sms_contacts, sms_smsstatus, sms_body, sms_phone) VALUES ('%s', %s, %s, %s, '%s') RETURNING sms_id" date contact sms-type (sql-escape-string text) phone))) 1174: (let* ((sql (format "INSERT INTO fromidentities VALUES (DEFAULT, %s, %s, NULL, NULL, NULL) ON CONFLICT(fromidentities_contacts) DO UPDATE SET fromidentities_identities = %s WHERE fromidentities.fromidentities_contacts = %s RETURNING fromidentities_id;" contact id id contact))) 1197: (sql (format "SELECT identities_id, concat_ws(', ',identities_name, identities_firstname, identities_lastname, identities_email) FROM identities WHERE identities_id IN (%s)" list)) 1208: (let* ((sql (format "UPDATE accounts SET accounts_identity = %s WHERE accounts_id = %s" identity id)) 1246: (sql (format "SELECT people_id, get_full_contacts_name(people_id) || ', ' || interactions_count FROM people, interactions WHERE interactions_count >= %s %s AND people_id = interactions_contacts ORDER BY interactions_count DESC LIMIT %s" interactions-min account limit))) 1252: (sql (format "SELECT accounts_id, accounts_name FROM accounts WHERE accounts_name ~* %s" query))) 1277: (sql (format "SELECT * FROM %s_combo" table))) 1310: (sql (format "SELECT * FROM %s_combo ORDER BY id DESC" table)) 1327: (sql (format "SELECT * FROM %s_combo ORDER BY id DESC" table))) 1397: (sql (format "INSERT INTO litems (litems_name, litems_currency, litems_purchasingvalue, litems_marketvalue, litems_salesvalue, litems_count, litems_lists) VALUES (%s, %s, %s, %s, %s, %s, %s) RETURNING litems_id" name currency purchasing-value market-value sales-value count list)) 1406: (let ((sql (format "SELECT litems_id, litems_name FROM litems, lists WHERE litems_lists = lists_id AND litems_lists = %s" id))) 1471: (sql (format "SELECT litems_name, litems_description, litems_url, litems_subtitle, litems_nofollow, litems_dateeffective FROM litems WHERE litems_lists = %s ORDER BY litems_priority, litems_id" id)) 1534: (let* ((sql (format "INSERT INTO peoplegroupmembers (peoplegroupmembers_person, peoplegroupmembers_peoplegroups) VALUES (%s, %s) RETURNING peoplegroupmembers_id" (pop marked) group)) 1669: (sql (format "SELECT contactskills_contacts, get_full_contacts_name(contactskills_contacts) FROM contactskills WHERE contactskills_skills = %s" skill)) 1677: (let* ((sql (format "SELECT contactskills_contacts, get_full_contacts_name(contactskills_contacts) FROM contactskills WHERE contactskills_skills = %s" id))) 1695: (let* ((sql (format "SELECT people_id, get_full_contacts_name(people_id) || ' ' || people_fax FROM people WHERE people_fax ~ '[0-9]' AND ((people_account1 = %s OR people_account2 = %s OR people_account3 = %s) OR (SELECT mailingsubscriptions_contacts FROM mailingsubscriptions WHERE mailingsubscriptions_contacts = people_id AND mailingsubscriptions_accounts = %s) = 1);" id id id id)) 1709: (sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(people_account1),'UNKNOWN') FROM people WHERE people_description ~* %s" query))) 1717: (let ((sql (format "UPDATE people SET people_account1 = %s WHERE people_account1 = %s" id other-account))) 1786: (sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(people_account1),'UNKNOWN') FROM people WHERE %s" where)) 1852: (let* ((sql (format "DELETE FROM %s WHERE %s_%s = %s AND %s_tags = %s" table table foreign id table tag-id))) 1860: (sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(people_account1),'UNKNOWN') FROM people WHERE people_description ~* %s AND (people_account1 = %s OR people_account2 = %s OR people_account3 = %s)" query account account account))) 1924: (let ((sql (format 2189: (let* ((sql (format "SELECT mailingsubscriptions_id FROM mailingsubscriptions WHERE mailingsubscriptions_accounts = %s AND mailingsubscriptions_contacts = %s" mid cid)) 2195: (sql (format "UPDATE mailingsubscriptions SET mailingsubscriptions_donotemail = TRUE, mailingsubscriptions_email = '%s', mailingsubscriptions_relatedemail = '%s', mailingsubscriptions_dateunsubscribed = now() WHERE mailingsubscriptions_accounts = %s AND mailingsubscriptions_contacts = %s" email eid mid cid))) 2200: (let* ((sql (format "UPDATE mailingsubscriptions SET mailingsubscriptions_donotemail = TRUE, mailingsubscriptions_email = '%s', mailingsubscriptions_dateunsubscribed = now() WHERE mailingsubscriptions_accounts = %s AND mailingsubscriptions_contacts = %s" email mid cid))) 2205: (sql (format "INSERT INTO mailingsubscriptions (mailingsubscriptions_donotemail, mailingsubscriptions_email, mailingsubscriptions_dateunsubscribed, mailingsubscriptions_accounts, mailingsubscriptions_contacts, mailingsubscriptions_relatedemail) VALUES (TRUE, '%s', now(), %s, %s, %s)" email mid cid eid))) 2209: (let* ((sql (format "INSERT INTO mailingsubscriptions (mailingsubscriptions_donotemail, mailingsubscriptions_dateunsubscribed, mailingsubscriptions_accounts, mailingsubscriptions_contacts, mailingsubscriptions_email) VALUES (TRUE, now(), %s, %s, '%s')" mid cid email))) 2220: (let* ((sql (format "SELECT mailingsubscriptions_id FROM mailingsubscriptions WHERE mailingsubscriptions_accounts = %s AND mailingsubscriptions_contacts = %s AND (mailingsubscriptions_donotemail IS NOT TRUE OR mailingsubscriptions_holdemail IS NOT TRUE)" account id)) 2226: (let ((sql (format "UPDATE mailingsubscriptions SET mailingsubscriptions_donotemail = FALSE WHERE mailingsubscriptions_accounts = %s AND mailingsubscriptions_contacts = %s AND mailingsubscriptions_donotemail IS TRUE" account id))) 2232: (sql (format "INSERT INTO mailingsubscriptions (mailingsubscriptions_accounts, mailingsubscriptions_contacts, mailingsubscriptions_email, mailingsubscriptions_referer, mailingsubscriptions_ip, mailingsubscriptions_assignedto, mailingsubscriptions_datecreated) VALUES (%s, %s, '%s', %s, %s, %s, '%s')" account id email (sql-escape-string referer) (sql-escape-string ip) assigned timestamp))) 2236: (let* ((sql (format "SELECT mailingsubscriptions_id FROM mailingsubscriptions WHERE mailingsubscriptions_accounts = %s AND mailingsubscriptions_contacts = %s AND mailingsubscriptions_donotemail IS NOT TRUE AND mailingsubscriptions_holdemail IS NOT TRUE" account id)) 2257: (let ((sql (format "INSERT INTO contactskills (contactskills_contacts, contactskills_skills) VALUES (%s, %s)" contact skill))) 2261: (let ((sql (format "INSERT INTO contactskills (contactskills_contacts, contactskills_skills) VALUES (%s, %s)" contact skill))) 2272: (let ((sql (format "INSERT INTO markassignments (markassignments_mark, markassignments_contact, markassignments_account2, markassignments_date) VALUES (%s, %s, %s, '%s')" mark id account date))) 2279: (sql (format "SELECT concat(markassignments_contact, ' ', get_full_contacts_name(markassignments_contact)) FROM markassignments WHERE markassignments_mark = %s AND markassignments_contact IS NOT NULL" mark)) 2287: (sql (format "SELECT markassignments_contact, get_full_contacts_name(markassignments_contact) FROM markassignments WHERE markassignments_mark = %s AND markassignments_contact IS NOT NULL" mark)) 2292: (let* ((sql (format "SELECT markassignments_id, marks_hid || ', ' || get_contacts_name(%s) FROM markassignments, marks WHERE marks_id = markassignments_mark AND (markassignments_contact = %s OR markassignments_contact2 = %s)" id id id)) 2302: (let ((sql (format "DELETE FROM markassignments WHERE markassignments_id = %s" mark-assignment))) 2325: (sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(people_account1),'') FROM people WHERE people_country1 = %s OR people_country2 = %s" country country))) 2329: (let* ((sql (format "SELECT people_id FROM people WHERE (people_account1 = %s OR people_account2 = %s OR people_account3 = %s) OR (SELECT mailingsubscriptions_contacts FROM mailingsubscriptions WHERE mailingsubscriptions_contacts = people_id AND mailingsubscriptions_accounts = %s) = 1;" id id id id))) 2333: (let* ((sql (format "SELECT people_id FROM people WHERE people_fax ~ '[0-9]' AND ((people_account1 = %s OR people_account2 = %s OR people_account3 = %s) OR (SELECT mailingsubscriptions_contacts FROM mailingsubscriptions WHERE mailingsubscriptions_contacts = people_id AND mailingsubscriptions_accounts = %s) = 1);" id id id id))) 2338: (let* ((sql (format "SELECT people_id || ' ' || get_full_contacts_name(people_id) || ', ' || coalesce(people_title,'') || ', ' || get_accounts_name(%s) || ', ' || coalesce(country_name(people_country1), 'Unknown country') || ', ' || coalesce(country_name(people_country2),'') FROM people WHERE (people_account1 = %s OR people_account2 = %s OR people_account3 = %s) OR (SELECT mailingsubscriptions_contacts FROM mailingsubscriptions WHERE mailingsubscriptions_contacts = people_id AND mailingsubscriptions_accounts = %s) = 1;" id id id id id))) 2348: (let* ((sql (format "SELECT people_id FROM people WHERE people_introducedby = %s ORDER BY people_id" id)) 2361: (let* ((sql (format "SELECT people_id || ' ' || get_contacts_name(people_id) FROM people WHERE people_introducedby = %s ORDER BY people_id" id))) 2376: (sql (format "INSERT INTO generallog (generallog_accounts, generallog_assignedto, generallog_date, generallog_time, generallog_title, generallog_description, generallog_publish) VALUES (%s, %s, %s, %s, %s, %s, TRUE) RETURNING generallog_id" account assigned-to date time title description))) 2387: (sql (format "INSERT INTO generallog (generallog_contacts, generallog_title) VALUES (1, %s)" title-2))) 2393: (let ((sql (format "SELECT generallog_id, generallog_title, coalesce(generallog_description,'') 2402: (let ((sql (format "SELECT people_id FROM people WHERE people_id != %s AND (people_email1 ILIKE '%s' OR people_email2 ILIKE '%s' OR people_email3 ILIKE '%s') ORDER BY people_id" id email email email))) 2421: (let* ((sql (format "SELECT people_id FROM people WHERE people_email1 ~* '%s' OR people_email2 ~* '%s' OR people_email3 ~* '%s' OR ((people_contacttype1 = 9 AND people_contact1 ~* '%s') OR (people_contacttype2 = 9 AND people_contact2 ~* '%s') OR (people_contacttype3 = 9 AND people_contact3 ~* '%s')) ORDER BY people_id" email email email email email email))) 2434: (sql (format "INSERT INTO notes (notes_contact, notes_name, notes_note) VALUES (%s, %s, %s) RETURNING notes_id" id name note)) 2462: (sql (format "UPDATE people SET %s = trim(both %s);\n" column column))) 2494: (let* ((sql (format "SELECT people_prefix, people_suffix FROM people WHERE people_id = %s;" id)) 2506: (sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(people_account1),'UNKNOWN') FROM people ORDER BY people_id DESC LIMIT %s" limit)) 2513: (let ((sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(people_account1),'UNKNOWN') FROM people WHERE people_id = %s" id)) 2538: (sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(people_account1),'UNKNOWN') FROM people WHERE people_id in (%s)" id-list)) 2591: (let ((sql (format "SELECT people_id || ' ' || get_full_contacts_name(people_id) || ' ' || coalesce(country_name(people_country1),' ') || coalesce(country_name(people_country2),' ') || contact_interactions(people_id) AS entry FROM people WHERE people_account1 = '%s' OR people_account2 = '%s' OR people_account3 = '%s' ORDER BY entry" id id id))) 2629: (sql (format "INSERT INTO emacsplaces (emacsplaces_hostname, emacsplaces_database, emacsplaces_table, emacsplaces_column, emacsplaces_dbid, emacsplaces_place) VALUES ('%s','%s','%s','%s',%s,%s) ON CONFLICT (emacsplaces_hostname, emacsplaces_database, emacsplaces_schema, emacsplaces_table, emacsplaces_table, emacsplaces_column, emacsplaces_dbid) DO UPDATE SET emacsplaces_place = %s WHERE emacsplaces.emacsplaces_hostname = '%s' AND emacsplaces.emacsplaces_database = '%s' AND emacsplaces.emacsplaces_table = '%s' AND emacsplaces.emacsplaces_column = '%s' AND emacsplaces.emacsplaces_dbid = %s;" hostname cf-database-name rcd-current-table rcd-current-column rcd-current-table-id (point) (point) hostname cf-database-name rcd-current-table rcd-current-column rcd-current-table-id))) 2636: (sql (format "SELECT emacsplaces_place FROM emacsplaces WHERE emacsplaces_hostname = '%s' AND emacsplaces_database = '%s' AND emacsplaces_schema = '%s' AND emacsplaces_table = '%s' AND emacsplaces_column = '%s' AND emacsplaces_dbid = '%s'" hostname cf-database-name "public" table column id))) 2649: (sql (format "SELECT accounts_id, accounts_name FROM accounts %s ORDER BY accounts_name" where))) 2666: (sql (format "SELECT accounts_id, accounts_name FROM accounts WHERE accounts_id IN (%s)" accounts))) 2671: (let* ((sql (format "SELECT CASE WHEN accounts_email1 ~ '@' THEN accounts_email1 ELSE NULL END AS email1, CASE WHEN accounts_email2 ~ '@' THEN accounts_email2 ELSE NULL END AS email2, CASE WHEN accounts_email3 ~ '@' THEN accounts_email3 ELSE NULL END AS email3 FROM accounts WHERE accounts_id = %s ORDER BY accounts_id LIMIT 1" account))) 2678: (sql (format "INSERT INTO notes (notes_account, notes_name, notes_note) VALUES (%s, %s, %s) RETURNING notes_id" id name note)) 2718: (let* ((sql (format "UPDATE people SET people_account1 = %s WHERE people_id = %s" account contact))) 2725: (let* ((sql (format "UPDATE people SET people_account2 = %s WHERE people_id = %s" account contact))) 2732: (let* ((sql (format "UPDATE people SET people_account3 = %s WHERE people_id = %s" account contact))) 2738: (sql (format "SELECT accounts_id, accounts_name FROM accounts WHERE accounts_accounttypes = %s" type))) 2748: (let* ((sql (format "SELECT emails_id, emails_subject FROM emails WHERE emails_mailinglist = %s ORDER BY emails_priority DESC" mid))) 2775: (let* ((sql (format "SELECT accounts_id, accounts_name || ' ' || CASE WHEN mailingsubscriptions_holdemail IS TRUE THEN ', ON HOLD' ELSE '' END AS hold FROM accounts, mailingsubscriptions WHERE mailingsubscriptions_accounts = accounts_id AND mailingsubscriptions_contacts = %s AND mailingsubscriptions_donotemail IS NOT TRUE" contact)) 2858: (let ((sql (format "SELECT CASE WHEN (SELECT count(mailingsubscriptions_id) FROM mailingsubscriptions WHERE mailingsubscriptions_contacts = %s) = 0 THEN NULL ELSE mailingsubscriptions_accounts || ' ' || get_accounts_name(mailingsubscriptions_accounts) END FROM mailingsubscriptions WHERE mailingsubscriptions_contacts = %s AND mailingsubscriptions_donotemail IS NOT TRUE" id id))) 2874: (let ((sql (format "SELECT date(mailings_datecreated) || ' ' || mailings_subject || ', ' || get_accounts_name(mailings_fromcompany) FROM mailings WHERE mailings_contacts = %s" id))) 2879: (let* ((sql (format "SELECT interactiontypes_name || ': ' || interactions_count FROM interactiontypes, interactions WHERE interactions_contacts = %s AND interactions_interactiontypes = interactiontypes_id" id))) 2884: (let* ((sql (format "SELECT interactiontypes_name, interactions_count FROM interactiontypes, interactions WHERE interactions_contacts = %s AND interactions_interactiontypes = interactiontypes_id" id)) 3039: (let ((sql (format "SELECT notes_id FROM notes WHERE notes_contact = %s ORDER BY notes_id" id))) 3043: (let ((sql (format "SELECT notes_id, notes_name, notes_note FROM notes WHERE notes_id = %s" id))) 3062: (let* ((sql (format "SELECT '\n** ' || sms_datecreated || '\n\n' || smsstatus_name || ' by number ' || sms_phone || '\n\n' || sms_body || '\n' FROM sms, smsstatus WHERE smsstatus_id = sms_smsstatus AND sms_contacts = %s ORDER BY sms_datecreated" id)) 3076: (let ((sql (format "SELECT DISTINCT interactions_contacts || ' ' || get_full_contacts_name(interactions_contacts) || ', ' || interactions_count FROM interactions WHERE interactions_count > %s" min))) 3081: (let* ((sql (format "SELECT * FROM people_by_interactions ORDER BY \"Interactions\"::integer DESC LIMIT %s" number-of-people))) 3088: (sql (format "SELECT people_id FROM people WHERE people_account1 IN (%s) ORDER BY people_id" accounts-greater-than)) 3091: (sql (format "SELECT * FROM people_by_interactions WHERE \"ID\" IN (%s) ORDER BY \"Interactions\"::integer DESC" list))) 3115: (sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(coalesce(people_account1,people_account2,people_account3)),'UNKNOWN') FROM people WHERE people_country1 = %s OR people_country2 = %s" country country)) 3125: (sql (format "SELECT people_id, interactions_count_people(people_id)::text AS count, get_full_contacts_name(people_id) FROM people WHERE people_id in (%s) ORDER BY count DESC" people))) 3135: (sql (format "INSERT INTO dbtranslations (dbtranslations_table, dbtranslations_field, dbtranslations_tableid, dbtranslations_language, dbtranslations_translation) VALUES ('%s', '%s', %s, %s, %s) ON CONFLICT DO NOTHING RETURNING dbtranslations_translation" table column id language-id (sql-escape-string translation)))) 3141: (let* ((sql (format "SELECT people_id FROM people WHERE people_email1 ILIKE '%s' OR people_email2 ILIKE '%s' OR people_email3 ILIKE '%s'" email email email)) 3184: (let ((sql (format "SELECT accounts_id, accounts_name, coalesce(country_name(accounts_billingcountry),'UNKNOWN') FROM accounts ORDER BY accounts_datecreated DESC LIMIT 200"))) 3190: (let* ((sql (format "SELECT mininglands_contacts, get_full_contacts_name(mininglands_contacts), mininglands_code, coalesce(country_name(people_country1), country_name(people_country2), 'UNKNOWN') FROM mininglands, people WHERE mininglands_contacts = people_id ORDER BY mininglands_id DESC"))) 3452: (sql (format "INSERT INTO people (people_lastname, people_account1, people_email1) VALUES ('%s',%s,'%s')" email account email))) 3474: (sql (format "SELECT people_id, get_full_contacts_name(people_id), get_accounts_name(people_account1) FROM people WHERE (people_invalid1 IS TRUE or people_invalid2 IS TRUE or people_invalid3) IS TRUE AND people_datecreated > current_timestamp - interval '%s days'" days))) 3482: (sql (format "SELECT people_id, sum(interactions_count)::text as sum, get_full_contacts_name(people_id) AS name FROM people, interactions WHERE interactions_contacts = people_id AND (people_account1 = %s OR people_account2 = %s OR people_account3 = %s) GROUP BY people_id, name ORDER BY sum DESC" account account account))) 3509: (sql (format "SELECT sum(interactions_count) FROM interactions WHERE %s" or-clause)) 3517: (sql (format "INSERT INTO interactions (interactions_interactiontypes, interactions_accounts, interactions_count) VALUES (11, %s, %s) ON CONFLICT (interactions_accounts,interactions_interactiontypes) DO UPDATE SET interactions_count = %s WHERE interactions.interactions_accounts = %s AND interactions.interactions_interactiontypes = 11;" id count count id))) 3557: (sql (format "SELECT people_id, get_full_contacts_name(people_id), get_accounts_name(people_account1) FROM people WHERE people_id in (%s)" emails)) 3578: (sql (format "INSERT INTO peopleactivities (peopleactivities_languages, peopleactivities_people, peopleactivities_activity, peopleactivities_locationtext, peopleactivities_contactline) VALUES (%s, %s, %s, %s, %s) RETURNING peopleactivities_id" language id activity location contact-line))) 3619: (let* ((sql (format "INSERT INTO relations (relations_contacts, relations_relationtypes, relations_tocontact, relations_description) VALUES (%s, %s, %s, %s)" contact type related-to-contact (sql-escape-string description))) 3628: (sql (format "SELECT relations_id, get_full_contacts_name(relations_contacts), relationtypes_name, get_full_contacts_name(relations_tocontact), relations_description FROM relations, relationtypes WHERE relationtypes_id = relations_relationtypes AND (relations_contacts = %s OR relations_tocontact = %s)" id id))) 3655: (let ((sql (format "INSERT INTO accounts (accounts_name) VALUES (%s) RETURNING accounts_id" name))) 3679: (let* ((sql (format "SELECT %s FROM %s WHERE %s" (string-join columns ", ") table where))) 3748: (let* ((sql (format "INSERT INTO domains (domains_name, domains_tlds, domains_ownercontact) VALUES ('%s', %s, %s)" domain tld contact))) 3763: (sql (format "SELECT attname, atttypid::regtype, attnotnull FROM pg_attribute WHERE attrelid = '%s.%s'::regclass AND attnum > 0 AND NOT attisdropped ORDER BY attnum" schema table)) 3769: (let* ((sql (format "SELECT description FROM pg_shdescription JOIN pg_database ON objoid = pg_database.oid WHERE datname = '%s'" table)) 3774: (let ((sql (format "SELECT pgd.description FROM pg_catalog.pg_statio_all_tables AS st INNER JOIN pg_catalog.pg_description pgd ON (pgd.objoid=st.relid) INNER JOIN information_schema.columns c ON (pgd.objsubid=c.ordinal_position AND c.table_schema=st.schemaname AND c.table_name=st.relname AND c.table_name = '%s' AND c.table_schema = 'public' AND c.column_name = '%s')" table column))) 3779: (sql (format "SELECT atttypid, attname FROM pg_attribute WHERE attrelid = '%s.%s'::regclass AND attnum > 0 AND NOT attisdropped ORDER BY attnum" schema table)) 3804: (sql (format "INSERT INTO %s (%s) SELECT %s FROM %s WHERE %s_id = %d RETURNING %s_id" 3816: (sql (format "SELECT '%s.%s'::regclass::oid" schema table)) 3822: (sql (format "SELECT 3864: (let* ((sql (format "SELECT a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod), (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef), a.attnotnull, a.attnum, (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type t WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation) AS attcollation, a.attidentity, NULL AS indexdef, NULL AS attfdwoptions, a.attstorage, CASE WHEN a.attstattarget=-1 THEN NULL ELSE a.attstattarget END AS attstattarget, pg_catalog.col_description(a.attrelid, a.attnum) FROM pg_catalog.pg_attribute a WHERE a.attrelid = '%s' AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum" oid)) 3894: (sql (format "SELECT description FROM pg_shdescription JOIN pg_database ON objoid = pg_database.oid WHERE datname = '%s'" database-name))) 3912: (sql (format "COMMENT ON COLUMN %s.%s IS %s" table column comment))) 3998: (sql (format "SELECT * FROM %s WHERE to_tsvector(%s::text) @@ to_tsquery('%s')" table table query))) 4003: (let* ((sql (format"SELECT n.nspname as \"Schema\", 4022: (let* ((sql (format"SELECT c.oid, c.relname as \"Name\", 4055: (let* ((sql (format"SELECT c.relname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','p','') AND n.nspname <> 'pg_catalog' AND n.nspname <> 'information_schema' AND n.nspname !~ '^pg_toast' AND pg_catalog.pg_table_is_visible(c.oid) ORDER BY c.relname"))) 4191: (sql (format "SELECT %s_id FROM %s WHERE %s = %s" table table column value)) 4215: (sql (format "UPDATE %s SET %s = %s WHERE %s_id = %s RETURNING %s" table column nvalue table id column))) 4245: (let* ((sql (format "SELECT * FROM meta_fields WHERE meta_fields_table = '%s' AND meta_fields_field = '%s'" table column))) 4410: (let ((sql (format "DELETE FROM %s WHERE %s_id = %s" table table id))) 4418: (let ((sql (format "DELETE FROM %s WHERE %s = %s" table where value))) 4426: (let ((sql (format "SELECT EXISTS ( 4436:;; (let ((sql (format "CREATE VIEW %s_combo AS SELECT %s_id AS id FROM %s ORDER BY %s" table table column table column))) 4445: (let ((sql (format "SELECT people_id, get_full_contacts_name(people_id), get_accounts_name(people_account1) FROM people WHERE people_leadsource = %s" lead-source))) 4474: (let ((sql (format "SELECT (SELECT string_agg(regexp_replace(x.v,'\n',' ','g'), ' ') FROM jsonb_each_text(to_jsonb(t)) AS x(k,v)) AS all_columns FROM %s t ORDER BY %s_id;" table table))) 4478: (let ((sql (format "SELECT concat_ws(' ', id, text) FROM %s_combo ORDER BY id" table))) 4482: (let* ((sql (format "SELECT concat(%s_list.*) FROM %s_list ORDER BY %s_id" table table table)) 4487: (let* ((sql (format "SELECT concat(%s.*) FROM %s ORDER BY %s_id" table table table)) 4516: (sql (format "UPDATE %s SET %s = regexp_replace(%s, %s, %s, 'g') WHERE %s ~ %s" table column column pattern replacement column pattern))) 4524: (sql (format "UPDATE %s SET %s = regexp_replace(%s, %s, %s, 'g') WHERE %s ~ %s" table column column pattern replacement column pattern))) 4539: (let* ((sql (format "SELECT %s FROM %s WHERE %s_id = %s" (string-join columns ", ") table table id))) 4589: (let* ((sql (format "UPDATE %s SET %s = NULL WHERE %s_id = %s" table column table id))) 4604: (sql (format "DELETE FROM %s a USING %s b WHERE a.%s_id > b.%s_id AND a.%s = b.%s %s" table table table table column column and-where))) 4641: (let* ((sql (format "SELECT * FROM %s" view)) 4714: (sql (format "UPDATE people SET people_tokens = to_tsvector(concat_ws(' ', people_firstname, people_middlenames, people_lastname, people_email1, people_email2, people_email3, get_accounts_name(people_account1), get_accounts_name(people_account2), get_accounts_name(people_account3), people_city1, CASE WHEN people_country1 IS NOT NULL THEN country_name(people_country1) ELSE '' END, coalesce((SELECT string_agg(tags_name,' ') FROM tags, peopletags WHERE peopletags_tags = tags_id AND peopletags_people = people_id),''), CASE WHEN people_country2 IS NOT NULL THEN country_name(people_country2) ELSE '' END, people_description, (select string_agg(sms_body,' ') from sms where sms_contacts = people_id))) %s" where))) 4725: (sql (format "SELECT documents_id, documents_name || ' ' || ts_rank_cd(to_tsvector(documents_name || ' ' || documents_description || ' ' || documents_document),%s,32 /* rank/(rank+1) */) AS rank FROM documents, to_tsquery(%s) query WHERE query @@ to_tsvector(documents_name || ' ' || documents_description || ' ' || documents_document) ORDER BY rank DESC LIMIT 30;" query query)) ;; TODO this cannot order by rank 4736: (let ((sql (format "SELECT unnest(%s) FROM %s WHERE %s_id = %s" column table table id))) 4842: (sql (format "INSERT INTO markassignments (markassignments_mark, markassignments_account, markassignments_contact, markassignments_date) VALUES (%s, %s, %s, '%s') RETURNING markassignments_id" mark account contact date))) 4894: (let* ((sql (format "SELECT people_id, get_full_contacts_name(people_id) FROM people WHERE people_introducedby = %s" id)) 4902: (let* ((sql (format "SELECT mailings_id, mailings_subject, date(mailings_datecreated), get_accounts_name(mailings_fromcompany) FROM mailings WHERE mailings_contacts = %s ORDER by mailings_datecreated" id))) 4922: (sql (format "SELECT people_id, get_full_contacts_name(people_id), get_accounts_name(people_account1) FROM people WHERE people_officephone ~ '%s' OR people_mobilephone ~ '%s' OR people_homephone ~ '%s' OR people_otherphone ~ '%s' OR people_fax ~ '%s'" number number number number number)) 4954: (let* ((sql (format "SELECT accounts_id, accounts_name FROM accounts WHERE accounts_id = %s" id))) 5002: (let* ((sql (format "SELECT notes_id, notes_name, notes_note FROM notes WHERE notes_contact = %s" id)) 5010: (let* ((sql (format "SELECT notes_id, notes_name FROM notes WHERE notes_account = %s" id)) 5022: (sql (format "INSERT INTO notes (notes_name, notes_contact, notes_note) VALUES (%s, %s, %s) RETURNING notes_id" name id note)) 5034: (sql (format "INSERT INTO notes (notes_name, notes_account, notes_note) VALUES (%s, %s, %s) RETURNING notes_id" name id note)) 5042: (let* ((sql (format "SELECT sms_id, sms_datecreated::date, smsstatus_name, sms_body FROM sms, smsstatus WHERE sms_contacts = %s AND smsstatus_id = sms_smsstatus" id)) 5071: (let* ((sql (format "INSERT INTO markassignments (markassignments_mark, markassignments_contact, markassignments_date) VALUES (%s, %s, '%s') RETURNING markassignments_id" mark id date)) 5078: (let ((sql (format "SELECT addressbookentries_people FROM addressbookentries WHERE addressbookentries_people = %s AND addressbookentries_addressbooks = %s" person-id addressbook))) 5084: (let ((sql (format "INSERT INTO addressbookentries (addressbookentries_addressbooks, addressbookentries_people) VALUES (%s, %s) RETURNING addressbookentries_id" addressbook person-id))) 5092: (let ((sql (format "DELETE FROM addressbookentries WHERE addressbookentries_addressbooks = %s AND addressbookentries_people = %s" addressbook person-id))) 5135: (sql (format "SELECT people_id, get_full_contacts_name(people_id) FROM people WHERE (people_mobilephone ~ '\\+%s' OR people_homephone ~ '\\+%s' OR people_homephone ~ '\\+%s' OR people_fax ~ '\\+%s') AND people_country1 IS NULL" prefix prefix prefix prefix))) 5142: (sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(people_account1),get_accounts_name(people_account2)) FROM people WHERE (people_mobilephone ~ '\\+%s' OR people_homephone ~ '\\+%s' OR people_homephone ~ '\\+%s' OR people_fax ~ '\\+%s') OR people_country1 = %s" prefix prefix prefix prefix country))) 5158: (sql (format "SELECT emails_id, emails_subject, get_accounts_name(emails_mailinglist) FROM emails WHERE emails_subject ~* %s" query))) 5165: (sql (format "SELECT emails_id, emails_subject, coalesce(get_accounts_name(emails_mailinglist),'UNKNOWN') FROM emails WHERE emails_body ~* %s" query))) 5176: (let* ((sql (format "SELECT domains_name || tlds_tld FROM domains, tlds WHERE domains_ownercontact = %s AND domains_tlds = tlds_id" id))) 5187: (let ((sql (format "SELECT accounts_id, accounts_name FROM accounts WHERE accounts_member1 = %s OR accounts_member2 = %s OR accounts_member3 = %s" id id id))) 5199: (sql (format "SELECT people_id, get_full_contacts_name(people_id) FROM people WHERE people_id IN (%s)" list)) 5262: (let ((sql (format "SELECT personaltransactions_id, personaltransactions_date, 5385: (let ((sql (format "SELECT id, text FROM %s_combo ORDER BY id" table))) 5426: (sql (format "COMMENT ON TABLE %s IS %s" table comment))) 5628: (sql (format "SELECT hyobjects_id FROM hyobjects WHERE %s = %s" column value))) 5746: (sql (format "SELECT people_id, get_full_contacts_name(people_id), coalesce(get_accounts_name(people_account1),get_accounts_name(people_account2),get_accounts_name(people_account3)) FROM people where people_tokens @@ to_tsquery('%s')" query))) 5753: (sql (format "UPDATE people SET people_tokens = to_tsvector(concat_ws(' ', people_firstname, people_middlenames, people_lastname, people_email1, people_email2, people_email3, get_accounts_name(people_account1), get_accounts_name(people_account2), get_accounts_name(people_account3), people_city1, CASE WHEN people_country1 IS NOT NULL THEN country_name(people_country1) ELSE '' END, CASE WHEN people_country2 IS NOT NULL THEN country_name(people_country2) ELSE '' END, people_description, (select string_agg(sms_body,' ') from sms where sms_contacts = people_id))) %s" where))) 5898: (sql (format "UPDATE %s SET %s = NULL WHERE %s_id = %s" table column table new-id))) 6164: (sql (format "SELECT count(1)::text FROM people WHERE people_country1 = %s OR people_country2 = %s" country country))) 6197: (let ((sql (format "SELECT pages_id, pages_title, areas_name FROM pages, areas WHERE areas_id = pages_area AND pages_pagetype = %s" id))) 6319: (sql (format "SELECT pages_id FROM pages WHERE pages_title !~~ 'EMPTY PAGE' AND pages_area = %s %s %s ORDER BY pages_id %s %s" area cat-sql excluded order limit)) 6530: (let* ((sql (format "SELECT pages_id, pages_title, 'page', pages_priority AS priority FROM pages WHERE pages_area = %s AND pages_categories IS NULL AND pages_notinmenu IS NOT TRUE UNION (SELECT categories_id, categories_name, 'category', categories_priority AS priority FROM categories WHERE categories_parent IS NULL and categories_area = %s AND categories_notinmenu IS NOT TRUE UNION SELECT pages_id, pages_title, 'page', pages_priority AS priority FROM pages WHERE pages_area = %s AND pages_categories IS NOT NULL AND pages_notinmenu IS NOT TRUE) ORDER BY priority" area area area)) 6571: (let ((sql (format "DELETE FROM pages WHERE pages_id = %d" id))) 6630: (sql (format "SELECT pages_id || ' ' || pages_title || ', ' || areas_name FROM pages, areas WHERE pages_area = areas_id AND (pages_title ~* '%s' OR pages_description ~* '%s')" query query)) 6767: (sql (format "SELECT tlds_id FROM tlds WHERE tlds_tld = '%s'" tld)) 6775: (sql (format "UPDATE pages SET pages_filename = '%s' WHERE pages_id = %s" slug page-id))) 6789: (sql (format "SELECT pages_id, pages_title, areas_name FROM pages, areas WHERE areas_id = pages_area %s ORDER BY areas_name" where))) 6795: (let ((sql (format "SELECT pages_id, pages_title, coalesce(pages_filename,''), areas_name FROM pages, areas WHERE areas_id = pages_area AND pages_area = %s" id))) 6810: (let ((sql (format "SELECT pages_title FROM pages WHERE pages_id = %s" id))) 6831: (let ((sql (format "UPDATE pages SET pages_ogimage = '%s' WHERE pages_id = %s AND pages_ogimage !~ '/'" (public-html-rest image-1536) id))) 6857: (let ((sql (format "SELECT pages_id FROM pages WHERE pages_area = %s AND pages_ogimage !~ '//'" area))) 6920: (sql (format "SELECT pages_id, pages_title, 'page', pages_priority AS priority, pages_notinmenu FROM pages WHERE pages_area = %s AND pages_categories IS NULL UNION ALL SELECT categories_id, categories_name, 'category', categories_priority, categories_notinmenu AS priority FROM categories WHERE categories_parent IS NULL and categories_area = %s ORDER BY priority DESC" area area)) 6932: (sql (format "SELECT pages_id, pages_title, 'page', pages_priority AS priority, pages_notinmenu FROM pages WHERE pages_area = %s AND pages_categories = %s UNION ALL SELECT categories_id, categories_name, 'category', categories_priority, categories_notinmenu AS priority FROM categories WHERE categories_parent = %s AND categories_area = %s ORDER BY priority DESC" area category category area)) 6951: (let* ((sql (format "INSERT INTO categories (categories_area, categories_parent, categories_slug, categories_name, categories_menuname) VALUES (%s, %s, '%s', %s, %s) RETURNING categories_id" area parent slug (sql-escape-string name) (sql-escape-string menu))) 6963: (sql (format "SELECT pages_id, pages_title || ', ' || pages_priority FROM pages WHERE pages_area = %s AND pages_categories %s" area category)) 7065: (let ((sql (format "SELECT categories_id, categories_name FROM categories WHERE categories_area = %s" id))) 7071: (sql (format "SELECT variables_id, variables_name FROM variables WHERE variables_area = %s" area))) 7092: (let ((sql (format "SELECT targets_id FROM targets WHERE targets_area = %d AND targets_active IS TRUE" area))) 7186: (let ((sql (format "SELECT pages_ogimage FROM pages WHERE pages_area = %d ORDER BY pages_id" area))) 7208: (let* ((sql (format "SELECT pages_priority FROM pages WHERE pages_categories = %s ORDER BY pages_priority DESC LIMIT 1" id))) 7238: (sql (format "INSERT INTO pages (pages_area, pages_filename, pages_title, pages_description, pages_keywords, pages_priority, pages_categories, pages_content, pages_templates) VALUES (%s, '%s', %s, %s, '%s', %s, %s, %s, %s) RETURNING pages_id" area filename (sql-escape-string title) (sql-escape-string description) keywords new-priority category (sql-escape-string page) template)) 7309: (let* ((sql (format "SELECT pages_id FROM pages WHERE pages_area = %s AND pages_content ~* %s" area (sql-escape-string query))) 7351: (sql (format "SELECT categories_id, parent_category_name(categories_id) || '::' || categories_name FROM categories %s ORDER BY categories_parent, categories_priority" where))) 7356: (let ((sql (format "SELECT pages_id FROM pages WHERE pages_filename = '%s' AND pages_categories = %s" slug id))) 7455: (sql (format "INSERT INTO pages (pages_area, pages_categories, pages_title, pages_description, pages_content, pages_keywords, pages_priority, pages_ogimage, pages_mediaurl, pages_mediatypes, pages_mediasize, pages_mainpage, pages_filename, pages_menuname, pages_active, pages_notinmenu, pages_content2, pages_templates) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING pages_id" area category (sql-escape-string title) (sql-escape-string description) (sql-escape-string body) (sql-escape-string keywords) new-priority (sql-escape-string ogimage) (sql-escape-string media) media-type media-size main (sql-escape-string slug) (sql-escape-string menu) active hidden (sql-escape-string body2) template)) 7462: (sql (format "SELECT pages_id FROM pages WHERE pages_content ~* %s" region)) 7557: (sql (format "INSERT INTO categories (categories_area, categories_parent, categories_slug, categories_name) VALUES (%s, %s, %s, %s) RETURNING categories_id;" area parent slug name)) 7576: (sql (format "SELECT pages_id FROM pages WHERE pages_area = %s 7836: (let* ((sql (format "SELECT pages_id FROM pages WHERE pages_area = %s AND pages_mediaurl = '%s'" area media)) 7846: (let ((sql (format "SELECT pages_id FROM pages WHERE pages_mediaurl = '%s'" media))) 7892: (let ((sql (format "SELECT mediatypes_name FROM pages, mediatypes WHERE mediatypes_id = pages_mediatypes AND pages_id = %s" page-id))) 7897: (let ((sql (format "SELECT pages_mediaurl FROM pages WHERE pages_id = %s" page-id))) 7996: (sql (format "SELECT pages_id FROM pages WHERE pages_area = %s AND pages_categories = %s AND pages_id != %s AND pages_filename = '%s' ORDER BY pages_id" area category checked-page slug)) 8019: (let* ((sql (format "SELECT categories_id FROM categories WHERE categories_area = %s ORDER BY categories_id" area))) 8025: (sql (format "SELECT pages_id FROM pages WHERE pages_area = %s AND pages_categories = %s %s ORDER BY pages_id" area category exclude-main))) 8063: (let ((sql (format "SELECT pages_id FROM pages WHERE pages_area = %s ORDER BY pages_id" area))) 8116: (let* ((sql (format "INSERT INTO hyobjects (hyobjects_language, hyobjects_name, hyobjects_link, hyobjects_description, hyobjects_text) SELECT pages_language, pages_title, '', pages_description, pages_content FROM pages WHERE pages_id = %s RETURNING hyobjects_id" id)) 8166: (sql (format "SELECT pages_id, pages_title, areas_name FROM pages, areas WHERE areas_id = pages_area AND pages_ogimage ~* %s ORDER BY pages_id" query))) 8174: (sql (format "SELECT pages_id, pages_title, areas_name FROM pages, areas WHERE areas_id = pages_area AND pages_mediaurl ~* %s ORDER BY pages_id" query))) 8255: (sql (format "SELECT categories_id, categories_name FROM categories 8280: (sql (format "SELECT pages_id FROM pages WHERE pages_notinmenu IS NOT TRUE AND pages_title !~~ 'EMPTY' %s ORDER BY pages_priority" parent)) 8361: (let ((sql (format "SELECT pages_id, pages_title, (select count(1) FROM relatedpages WHERE relatedpages_pages1 = pages_id OR relatedpages_pages2 = pages_id)::text AS related FROM pages WHERE pages_area = %d ORDER BY related DESC" area))) 8370: (sql (format "SELECT pages_id, pages_title, (select count(1) FROM relatedpages WHERE relatedpages_pages1 = pages_id OR relatedpages_pages2 = pages_id)::text AS related FROM pages WHERE pages_area = %d AND (pages_content ~* %s OR pages_title ~* %s) ORDER BY related DESC" area query query))) 8384: (sql (format "SELECT pages_id, pages_title FROM pages WHERE pages_content ~* %s" query))) 8388: (let* ((sql (format "SELECT categories_id, categories_name, count(pages_id)::text FROM categories, pages WHERE pages_categories = categories_id AND categories_area = %s GROUP BY categories_id ORDER BY categories_priority DESC" area))) 8394: (let ((sql (format "SELECT relatedpages_pages2, pages_title, areas_name FROM relatedpages, pages,areas WHERE relatedpages_pages1 = %d AND pages_id = relatedpages_pages2 AND pages_area = areas_id UNION SELECT relatedpages_pages1, pages_title, areas_name FROM relatedpages, pages, areas WHERE relatedpages_pages2 = %d AND pages_id = relatedpages_pages1 AND pages_area = areas_id" id id))) 8444: (let ((sql (format "SELECT targets_id FROM targets WHERE targets_area = %s AND targets_active IS TRUE" area))) 8479: (sql (format "INSERT INTO personaltransactions (personaltransactions_name, personaltransactions_date, personaltransactions_amount, personaltransactions_currency, personaltransactions_fromperson, personaltransactions_fromaccount, personaltransactions_toperson, personaltransactions_toaccount, personaltransactions_description, personaltransactions_signature) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) RETURNING personaltransactions_id" name date amount currency from-person from-account to-person to-account description signature))) 8526: (sql (format "SELECT people_id, get_full_contacts_name(people_id), accounts_name FROM people, accounts WHERE people_account1 = accounts_id AND people_country1 = 224 AND accounts_name ~* 'jiji' AND people_mobilephone ~ '25677' AND people_id NOT IN (%s)" sms))) 8539: (sql (format "SELECT people_id, get_full_contacts_name(people_id), accounts_name FROM people, accounts WHERE people_account1 = accounts_id AND 8556: (sql (format "SELECT people_id, get_full_contacts_name(people_id), accounts_name FROM people, accounts WHERE people_account1 = accounts_id AND 8591: (sql (format "SELECT people_id, get_full_contacts_name(people_id) FROM people WHERE (substring(people_officephone, 2, 6) IN (%s) OR substring(people_mobilephone, 2, 6) IN (%s) OR substring(people_homephone, 2, 6) IN (%s) OR substring(people_otherphone, 2, 6) IN (%s) OR substring(people_fax, 2, 6) IN (%s)) ORDER BY people_id DESC LIMIT %s" prefixes prefixes prefixes prefixes prefixes how-many))) 8611: (let ((sql (format "SELECT locations_id, locations_name, locations_priority::text FROM locations WHERE locations_locationsets = %s ORDER BY locations_priority, locations_id DESC" id))) 8649: (sql (format "INSERT INTO locations (locations_locationsets, locations_geocoordformats, locations_name, locations_description, locations_latitude, locations_longitude, locations_contacts) VALUES (%s, %s, %s, %s, %s, %s, %s) RETURNING locations_id" id geocoordformat name description latitude longitude person)) 8665: (sql (format "INSERT INTO peoplegroups (peoplegroups_name, peoplegroups_description) VALUES (%s, %s) RETURNING peoplegroups_id" name description)) 8684: (sql (format "SELECT peoplegroupmembers_id, get_full_contacts_name(peoplegroupmembers_person), coalesce(get_accounts_name(people_account1),get_accounts_name(people_account2),get_accounts_name(people_account2),'UNKNOWN') FROM peoplegroupmembers, people WHERE people_id = peoplegroupmembers_person %s" group))) 8697: (sql (format "INSERT INTO peoplegroupmembers (peoplegroupmembers_person, peoplegroupmembers_peoplegroups, peoplegroupmembers_description) VALUES (%s, %s, %s) RETURNING peoplegroupmembers_id" person group description)) 8715: ;; (sql (format "INSERT INTO contactskills (contactskills_skills, contactskills_contacts) VALUES (107, %s)" person))) 8805: (let ((sql (format "SELECT (DATE_PART('day', '%s'::timestamp - '%s'::timestamp) * 24 8826: (let ((sql (format "SELECT '%s'::timestamp + interval '%s'" timestamp interval))) 8833: (sql (format "SELECT CASE WHEN current_timestamp::time < '%s' 8961: (sql (format "INSERT INTO reminders (reminders_name, reminders_remindertypes) -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-21 20:36 ` Emacs Modular Configuration: the preferable way Jean Louis @ 2021-06-21 21:15 ` tomas 2021-06-21 21:29 ` Jean Louis 2021-06-22 0:23 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 2 replies; 86+ messages in thread From: tomas @ 2021-06-21 21:15 UTC (permalink / raw) To: help-gnu-emacs [-- Attachment #1: Type: text/plain, Size: 1408 bytes --] On Mon, Jun 21, 2021 at 11:36:25PM +0300, Jean Louis wrote: > * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-21 17:12]: > > But you still see extremely bad habits "out there" which wouldn't be > > necessary these days -- because, well, they are "out there" (for > > example: assebling SQL queries with sprintf [1]). They take a life > > of their own :-) > > > > Cheers > > [1] https://xkcd.com/327/ > > Your small reference is definitely a possible danger if SQL input is > anyhow exposed [...] M< hint was rather a metaphor: using string operations on things that aren't really strings (in the original case: file system paths) can lead to surprising results. > the danger mentioned on the funny comic is practically non-existent as > it will never take place on my side [...] But your side is not "the world", and therefore Eli's warning was spot-on. Someone will browse the mail archives and copy your solution without knowing the dangers. > I am heavy user of the Emacs package: emacs-libpq @ Github > https://github.com/anse1/emacs-libpq No idea and no bandwidth to read it all. If you are tied to PostgreSQL (a good choice, I'd say), consider using prepared queries: they do what client-side template expansion (even the careful kind, with unescaping and all), and I'd expect them to do it much better, since PostgreSQL knows its own syntax best. Cheers - t [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-21 21:15 ` Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] tomas @ 2021-06-21 21:29 ` Jean Louis 2021-06-22 0:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:23 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-21 21:29 UTC (permalink / raw) To: tomas; +Cc: help-gnu-emacs * tomas@tuxteam.de <tomas@tuxteam.de> [2021-06-22 00:17]: > > the danger mentioned on the funny comic is practically non-existent as > > it will never take place on my side [...] > > But your side is not "the world", and therefore Eli's warning was > spot-on. Someone will browse the mail archives and copy your solution > without knowing the dangers. I agree on that. But we cannot possibly expect all possible dangers to be known by all possible programmers at all times especially on this mailing list, and then in so many external Emacs Packages. My intention to improve is (should) be perceivable. The email you are replying to is a proof that I did not claim it is "solution" at all. Quite contrary, I have validated your point and found 400+ possible problems in the program. It should be clear it is not a definite solution to every reader. Programs develop. They are never perfect until they get perfect. Without a single occurence of the incident with SQL it is exaggeration to say there is practical danger, rather hypothetical danger. Then when we speak of the PostgreSQL, users should anyway not be given permissions to DROP tables as that should be left to administrators. There is similar approach to updates of tables, there is row level security and users can update whatever they are permitted to, but not what they are not permitted to. All the dangers we speak about are usually solved at the database level. > > I am heavy user of the Emacs package: emacs-libpq @ Github > > https://github.com/anse1/emacs-libpq > > No idea and no bandwidth to read it all. If you are tied to > PostgreSQL (a good choice, I'd say), consider using prepared > queries: they do what client-side template expansion (even the > careful kind, with unescaping and all), and I'd expect them to > do it much better, since PostgreSQL knows its own syntax best. I will do, thanks. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-21 21:29 ` Jean Louis @ 2021-06-22 0:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:47 ` Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:31 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: > I agree on that. But we cannot possibly expect all possible > dangers to be known by all possible programmers at all times > especially on this mailing list OK, so the SQL injection is a common attack vector, but what should we call this issue? Uhm, the well-known and feared Windows vulnerability, let's see, argh, the Emacs Lisp string file system path attack vector? I don't know, it doesn't quite have the same ring to it... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 0:31 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:47 ` Jean Louis 2021-06-26 6:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-22 0:47 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-06-22 03:32]: > Jean Louis wrote: > > > I agree on that. But we cannot possibly expect all possible > > dangers to be known by all possible programmers at all times > > especially on this mailing list > > OK, so the SQL injection is a common attack vector, but what > should we call this issue? It is probably lack of database administration skills. It is nothing related to Emacs really. There is nothing special to SQL then to any other kind of user's input. In fact, PostgreSQL and MySQL or MariaDB are rather safe databases. If user does not have permission to DROP tables or do something malicious, then it does not have it, finished there. One can try it, but it will not work. On the other hand injecting simple malicious Emacs Lisp anywhere in any file is as a possible option omni-present on Internet, and we don't even speak about that. Thousands of users are blindly accepting programs from MELPA or any kind of ELPA without knowing what is going to happen with the data. And then we worry about possible SQL injections in Emacs Lisp. I just wonder how and where SQL injection. Is it maybe by malicious staff members versed in PostgreSQL? Or maybe Emacs Lisp running some sensitive data online (without backup) being exposed to online crackers trying to cheat the code and DROP some tables or do other bad stuff? It is so unlikely to take place. Bounty is US $10 from my side if somebody succeeds to SQL inject in my software a DROP of a table. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 0:47 ` Jean Louis @ 2021-06-26 6:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-28 6:56 ` Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 6:31 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >>> I agree on that. But we cannot possibly expect all >>> possible dangers to be known by all possible programmers >>> at all times especially on this mailing list >> >> OK, so the SQL injection is a common attack vector, but >> what should we call this issue? > > It is probably lack of database administration skills. It is > nothing related to Emacs really. It doesn't? :) > There is nothing special to SQL then to any other kind of > user's input. In fact, PostgreSQL and MySQL or MariaDB are > rather safe databases. I think that has turned into a schoolbook example because it has a cool name and everyone will understand it instantly. So it can serve the educational purpose to illuminate this in all of computing to not execute or use user input, without checking it out first. Indeed it would surprise me if you could just do it out-of-the-box for modern database management systems and expect it to be just wide open there for you to do it. > On the other hand injecting simple malicious Emacs Lisp > anywhere in any file is as a possible option omni-present on > Internet, and we don't even speak about that. Well, it doesn't work like that, really. > Thousands of users are blindly accepting programs from MELPA Ha ha, thousands of users are doing that blindly! My, my. How many people are doing it with ONE EYE open, you think? M-x how-many RET > And then we worry about possible SQL injections in Emacs > Lisp. No we aren't... > Bounty is US $10 from my side if somebody succeeds to SQL > inject in my software a DROP of a table. But where are your tables? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-26 6:31 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-28 6:56 ` Jean Louis 2021-07-06 1:57 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-28 6:56 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg <moasenwood@zoho.eu> [2021-06-26 02:31]: > > There is nothing special to SQL then to any other kind of > > user's input. In fact, PostgreSQL and MySQL or MariaDB are > > rather safe databases. > > I think that has turned into a schoolbook example because it > has a cool name and everyone will understand it instantly. > So it can serve the educational purpose to illuminate this in > all of computing to not execute or use user input, without > checking it out first. Indeed it would surprise me if you > could just do it out-of-the-box for modern database management > systems and expect it to be just wide open there for you to > do it. There is way to go and that is by providing parameters that are automatically escaped. pq:query is a module function. (pq:query CONN COMMAND &rest PARAMETERS) Execute COMMAND on CONN with optional PARAMETERS. Run an SQL command on a connection obtained by ‘pq:connectdb’. If PARAMETERS are used, you can reference them in COMMAND using $1, $2, ..., $12. Return the list of rows returned by the last statement in COMMAND. Rows are returned as atomic values if the statement yields a single column, or a vector of values if it yields more than one column. I am anyway SQL escaping all of the input values to database. Since we talked I have moved to better workflow and now I am first preparing one part of the SQL command without user's input and then using the user's input as a parameter that prevents those problems. I just guess it should be similar in MariaDB or MySQL. But I don't use it due to lack of readline and command expansion. > > On the other hand injecting simple malicious Emacs Lisp > > anywhere in any file is as a possible option omni-present on > > Internet, and we don't even speak about that. > > Well, it doesn't work like that, really. It is about the same danger. Practically there was never danger on my side as it is me who is using the database which is motly the case with many database applications. Problem comes with a large users base where malicious people may start doing something to the company or public or unknown crackers or script kiddies. It is better not to classify possible problematic sources and just do it more safe. > > Thousands of users are blindly accepting programs from MELPA > > Ha ha, thousands of users are doing that blindly! My, my. > How many people are doing it with ONE EYE open, you think? Well, without watching in the code. Click and install. There is no real security involved and users don't watch what is being installed, as Internet is large it is quite easy to create a game and make backdoor in Emacs or do other malicious stuff. It is also possible to make a module and do same. Until we know it, we cannot know it. > > Bounty is US $10 from my side if somebody succeeds to SQL > > inject in my software a DROP of a table. > > But where are your tables? Find it for the bounty. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-28 6:56 ` Jean Louis @ 2021-07-06 1:57 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-07-06 20:04 ` Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 1:57 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: > MySQL [...] "My" is a Swedish girl name if you didn't know. (And maybe a Danish, Finish, and Norwegian name as well.) So it isn't a possessive pronoun, here, even! Eheh, LISA, anyone? No, this is more clever! And better. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-07-06 1:57 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 20:04 ` Jean Louis 2021-07-06 20:19 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-07-06 20:04 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-07-06 05:01]: > Jean Louis wrote: > > > MySQL [...] > > "My" is a Swedish girl name if you didn't know. (And maybe > a Danish, Finish, and Norwegian name as well.) So it isn't > a possessive pronoun, here, even! It makes sense now, maybe she felt the international pressure and confusion, so she changed to Maria? -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-07-06 20:04 ` Jean Louis @ 2021-07-06 20:19 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 20:19 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >> "My" is a Swedish girl name if you didn't know. (And maybe >> a Danish, Finish, and Norwegian name as well.) So it isn't >> a possessive pronoun, here, even! > > It makes sense now, maybe she felt the international > pressure and confusion, so she changed to Maria? A sweet theory of yours no doubt, here is the actual story tho: https://mariadb.com/kb/en/the-aria-name/ -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-21 21:15 ` Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] tomas 2021-06-21 21:29 ` Jean Louis @ 2021-06-22 0:23 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 12:12 ` Eli Zaretskii 1 sibling, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:23 UTC (permalink / raw) To: help-gnu-emacs tomas wrote: > My hint was rather a metaphor: using string operations on > things that aren't really strings (in the original case: > file system paths) Emacs disagrees: (setq file "~/.emacs") (file-exists-p file) ; t (stringp file) ; t > But your side is not "the world", and therefore Eli's > warning was spot-on False alarm, as shown. It is safe to say, that warning can be ignored. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 0:23 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 12:12 ` Eli Zaretskii 2021-06-22 12:37 ` Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Eli Zaretskii @ 2021-06-22 12:12 UTC (permalink / raw) To: help-gnu-emacs > Date: Tue, 22 Jun 2021 02:23:03 +0200 > From: Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> > > tomas wrote: > > > My hint was rather a metaphor: using string operations on > > things that aren't really strings (in the original case: > > file system paths) > > Emacs disagrees: > > (setq file "~/.emacs") > (file-exists-p file) ; t > (stringp file) ; t > > > But your side is not "the world", and therefore Eli's > > warning was spot-on > > False alarm, as shown. It is safe to say, that warning can > be ignored. Not a false alarm; ignore that warning at your own peril: (string-equal "~/foo" "/home/users/eliz/foo") => nil (file-equal-p "~/foo" "/home/users/eliz/foo") => t and also: (string-equal "/home/users/eliz/foo" "/server/homes/users/eliz/foo") => nil (file-equal-p "/home/users/eliz/foo" "/server/homes/users/eliz/foo") => t And what about the below, what's going on there? $ ls -l /usr/bin/emacs* -rwxr-xr-x 2 eliz None 81081674 2021-03-25 15:54 /usr/bin/emacs -rwxr-xr-x 2 eliz None 81081674 2021-03-25 15:54 /usr/bin/emacs-27.2 (file-equal-p "/usr/bin/emacs" "/usr/bin/emacs-27.2") => t ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 12:12 ` Eli Zaretskii @ 2021-06-22 12:37 ` Jean Louis 2021-06-22 13:10 ` Eli Zaretskii 2021-06-26 6:39 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 2 replies; 86+ messages in thread From: Jean Louis @ 2021-06-22 12:37 UTC (permalink / raw) To: Eli Zaretskii; +Cc: help-gnu-emacs * Eli Zaretskii <eliz@gnu.org> [2021-06-22 15:14]: > > Date: Tue, 22 Jun 2021 02:23:03 +0200 > > Emacs disagrees: > > > > (setq file "~/.emacs") > > (file-exists-p file) ; t > > (stringp file) ; t > > > > > But your side is not "the world", and therefore Eli's > > > warning was spot-on > > > > False alarm, as shown. It is safe to say, that warning can > > be ignored. > > Not a false alarm; ignore that warning at your own peril: > > (string-equal "~/foo" "/home/users/eliz/foo") => nil > (file-equal-p "~/foo" "/home/users/eliz/foo") => t > > and also: > > (string-equal "/home/users/eliz/foo" "/server/homes/users/eliz/foo") => nil > (file-equal-p "/home/users/eliz/foo" > "/server/homes/users/eliz/foo") => t The above example is insightful. Though it does not change the fact that even `file-equal-p' function uses strings as its parameters. Of course it is handling files with their file names represented in strings accordingly to the file system. The meaning of a string did not change its type. (rcd-db-connect DATABASE &optional PORT HOST USERNAME PASSWORD) The meaning of a string DATABASE will not change the type of a string accepted. It would not be clear to say that DATABASE is not just a string because if I provide wrong name of the database I would never connect to it. There is diffference between the meaning and type. > And what about the below, what's going on there? > > $ ls -l /usr/bin/emacs* > > -rwxr-xr-x 2 eliz None 81081674 2021-03-25 15:54 /usr/bin/emacs > -rwxr-xr-x 2 eliz None 81081674 2021-03-25 15:54 /usr/bin/emacs-27.2 > > (file-equal-p "/usr/bin/emacs" "/usr/bin/emacs-27.2") => t (type-of "/usr/bin/emacs") ⇒ string (type-of "/usr/bin/emacs-27.2") ⇒ string Repeat after me: "The meaning of a string is not equal to its type.." ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 12:37 ` Jean Louis @ 2021-06-22 13:10 ` Eli Zaretskii 2021-06-22 15:45 ` Jean Louis 2021-06-26 6:39 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 1 reply; 86+ messages in thread From: Eli Zaretskii @ 2021-06-22 13:10 UTC (permalink / raw) To: help-gnu-emacs > Date: Tue, 22 Jun 2021 15:37:46 +0300 > From: Jean Louis <bugs@gnu.support> > Cc: help-gnu-emacs@gnu.org > > > (string-equal "~/foo" "/home/users/eliz/foo") => nil > > (file-equal-p "~/foo" "/home/users/eliz/foo") => t > > > > and also: > > > > (string-equal "/home/users/eliz/foo" "/server/homes/users/eliz/foo") => nil > > (file-equal-p "/home/users/eliz/foo" > > "/server/homes/users/eliz/foo") => t > > The above example is insightful. Though it does not change the fact > that even `file-equal-p' function uses strings as its parameters. We _represent_ file names as strings, but they are not normal strings. Just like characters are represented as integers, but they are not just simple integers, they have additional special attributes and behaviors. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 13:10 ` Eli Zaretskii @ 2021-06-22 15:45 ` Jean Louis 2021-06-22 16:04 ` Eli Zaretskii 2021-06-26 6:41 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 2 replies; 86+ messages in thread From: Jean Louis @ 2021-06-22 15:45 UTC (permalink / raw) To: Eli Zaretskii; +Cc: help-gnu-emacs * Eli Zaretskii <eliz@gnu.org> [2021-06-22 16:11]: > We _represent_ file names as strings, but they are not normal strings. > Just like characters are represented as integers, but they are not > just simple integers, they have additional special attributes and > behaviors. I get your point, what I don't agree with is the Formulierung. It is for same reason as you mentioned it, people are reading our writings and our form or text should be possibly clear. If you wish to say they are not normal strings, demonstrate it. By demonstration below it shows to be of type string. What is else there? I have a file: ~/tmp/new.txt This works fine: (find-file "~/tmp/new.txt") ⇒ #<buffer new.txt> Is it normal string? (type-of "~/tmp/new.txt") ⇒ string Of course I know there are functions that will get file attributes, and those are fine. Of course that meanings of strings are so much different. But subject was that we deal with strings in those functions. It was not about the meaning of strings. I have functions which chunk human names in 3 parts. Functions use strings. It really does not matter that I want to parse the human names and chunk it or fit it into some form, or do something with it. It does not change the type of a string and fact that strings are supplied to functions. The function `file-attributes' gives some different type as a result: (file-attributes "~/tmp/new.txt") ⇒ (nil 1 1001 1001 (24786 1053 990790 326000) (24786 1033 720790 188000) (24786 1033 720790 188000) 0 "-rw-r--r--" t 51912267 65024) (type-of (file-attributes "~/tmp/new.txt")) ⇒ cons Then we can work on that with: (setq attributes (file-attributes "~/tmp/new.txt")) (file-attribute-size attributes) ⇒ 0 (file-attribute-status-change-time attributes) ⇒ (24786 1033 720790 188000) I do understand you wish to point out to functions which interpret and represent the meanings. It still did not change the fact that string was supplied to it: "~/tmp/new.txt" Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 15:45 ` Jean Louis @ 2021-06-22 16:04 ` Eli Zaretskii 2021-06-22 18:01 ` Jean Louis 2021-06-26 6:41 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 1 reply; 86+ messages in thread From: Eli Zaretskii @ 2021-06-22 16:04 UTC (permalink / raw) To: help-gnu-emacs > Date: Tue, 22 Jun 2021 18:45:56 +0300 > From: Jean Louis <bugs@gnu.support> > Cc: help-gnu-emacs@gnu.org > > * Eli Zaretskii <eliz@gnu.org> [2021-06-22 16:11]: > > We _represent_ file names as strings, but they are not normal strings. > > Just like characters are represented as integers, but they are not > > just simple integers, they have additional special attributes and > > behaviors. > > I get your point, what I don't agree with is the Formulierung. It > is for same reason as you mentioned it, people are reading our > writings and our form or text should be possibly clear. If you > wish to say they are not normal strings, demonstrate it. By > demonstration below it shows to be of type string. What is else > there? What is there is that not every operation, which is valid and has trivially-expected results with strings, is valid and has the same trivial results with file names. See the examples I presented. And there's more, for example, (concat "/foo/" "/bar") could be equivalent to "/bar" when those are file names. Likewise with characters: if c is a valid character, (* 2 c) may not be a valid character, even if it is a valid number. > But subject was that we deal with strings in those functions. And my point is that it is dangerous (a.k.a. "wrong") using string functions on file names when there are specially-designed file-name functions for those use cases. Because those special-purpose functions are there for a reason, and disregarding those reasons is asking for trouble. Like using string comparison for comparing file names: that was actually a reason for quite a few bugs in our code. My point was trying to prevent people from making those same mistakes. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 16:04 ` Eli Zaretskii @ 2021-06-22 18:01 ` Jean Louis 2021-06-22 18:25 ` Eli Zaretskii 2021-06-26 6:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 2 replies; 86+ messages in thread From: Jean Louis @ 2021-06-22 18:01 UTC (permalink / raw) To: Eli Zaretskii; +Cc: help-gnu-emacs * Eli Zaretskii <eliz@gnu.org> [2021-06-22 19:14]: > And my point is that it is dangerous (a.k.a. "wrong") using string > functions on file names when there are specially-designed file-name > functions for those use cases. Because those special-purpose > functions are there for a reason, and disregarding those reasons is > asking for trouble. Like using string comparison for comparing file > names: that was actually a reason for quite a few bugs in our code. > My point was trying to prevent people from making those same mistakes. I agree that dedicated file functions should be used whenever possible. Now I am looking in some of my functions to review that: People have their ID number, so directory may exist for each person. But I cannot see a possibility to work with file paths that are structured without using string functions. I can maybe verify if some possible string represents directory or file, if it exists or if it is readable, but more than that, I would not know practically what to do. Maybe my scope of using such generated file paths is out of the mentioned scope. To summarize, it is better to use file related functions whenever possible, checking if it is directory, using functions like `file-name-as-directory' and so on. Avoiding string functions related to files seem to be now impossible. Like here below I have to `concat' or concatenate directory with the file base name, as when I do "filing" it is rather filed by year/month/date and either `concat' or format' has to be used. (dolist (file files) (let* ((basename (file-name-nondirectory file)) (target (concat date-dir basename)) (target (rcd-unique-file-name target))) (if (file-exists-p file) (progn (message (format "cf/file-by-contact: moving \"%s\" to \"%s\"" file target)) (rename-file file target)) (error (format "File does not exist: %s" file))))))) (defun cf-directory-by-id (id) "Opens the dired directory for ID" (let* ((dir (dir-id id))) (unless (file-directory-p dir) (make-dir-id id)) (dired dir))) (defun dir-id (id) "Returns directory for contact ID" (format "%s/%s/" (rcd-crm-directory-by-id) id)) (defun rcd-crm-directory-by-id () (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) (defun rcd-crm-directory-data () "Returns default CRM related directories" (let* ((sql "SELECT defaults_crmdir, defaults_crmbyid, defaults_crmbyname, defaults_crmdiraccount FROM defaults") (dirs (rcd-sql-first sql cf-db)) (crmdir (aref dirs 0)) (crmbyid (aref dirs 1)) (crmbyname (aref dirs 2)) (crmdiraccount (aref dirs 3))) (list crmdir crmbyid crmbyname crmdiraccount))) (defun rcd-crm-directory () (car (rcd-crm-directory-data))) (defun rcd-crm-directory-by-id () (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) I can now think of safer functions something like: `file-concat' that could or make sure that concatenated directories and file on the end exist or not. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 18:01 ` Jean Louis @ 2021-06-22 18:25 ` Eli Zaretskii 2021-06-26 6:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 0 replies; 86+ messages in thread From: Eli Zaretskii @ 2021-06-22 18:25 UTC (permalink / raw) To: help-gnu-emacs > Date: Tue, 22 Jun 2021 21:01:59 +0300 > From: Jean Louis <bugs@gnu.support> > Cc: help-gnu-emacs@gnu.org > > Avoiding string functions related to files seem to be now impossible. I never said anything to the contrary. > (defun rcd-crm-directory-by-id () > (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) > > > I can now think of safer functions something like: `file-concat' > that could or make sure that concatenated directories and file on > the end exist or not. It depends on what you concatenate. Whenever you concatenate a directory and a file under that directory, expand-file-name is a better choice. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 18:01 ` Jean Louis 2021-06-22 18:25 ` Eli Zaretskii @ 2021-06-26 6:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 7:15 ` Eli Zaretskii 2021-06-28 6:59 ` Jean Louis 1 sibling, 2 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 6:46 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: > To summarize, it is better to use file related functions > whenever possible, checking if it is directory, using > functions like `file-name-as-directory' and so on. Yes, of course. > (format "%s/%s/" (rcd-crm-directory-by-id) id)) > (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) > (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) Is this what you are not allowed to do? I ask because it looks similar to mine, only not as good, perhaps. Ha. OK, how is it suppose to look then? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-26 6:46 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 7:15 ` Eli Zaretskii 2021-06-28 7:04 ` Jean Louis 2021-06-28 6:59 ` Jean Louis 1 sibling, 1 reply; 86+ messages in thread From: Eli Zaretskii @ 2021-06-26 7:15 UTC (permalink / raw) To: help-gnu-emacs > Date: Sat, 26 Jun 2021 08:46:06 +0200 > From: Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> > > Jean Louis wrote: > > > (format "%s/%s/" (rcd-crm-directory-by-id) id)) > > (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) > > (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) > > Is this what you are not allowed to do? > > I ask because it looks similar to mine, only not as good, > perhaps. Ha. > > OK, how is it suppose to look then? Like this: (expand-file-name (cadr (rcd-crm-directory-data)) (rcd-crm-directory)) ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-26 7:15 ` Eli Zaretskii @ 2021-06-28 7:04 ` Jean Louis 2021-07-06 2:05 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-28 7:04 UTC (permalink / raw) To: Eli Zaretskii; +Cc: help-gnu-emacs * Eli Zaretskii <eliz@gnu.org> [2021-06-26 03:15]: > > Date: Sat, 26 Jun 2021 08:46:06 +0200 > > From: Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> > > > > Jean Louis wrote: > > > > > (format "%s/%s/" (rcd-crm-directory-by-id) id)) > > > (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) > > > (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) > > > > Is this what you are not allowed to do? > > > > I ask because it looks similar to mine, only not as good, > > perhaps. Ha. > > > > OK, how is it suppose to look then? > > Like this: > > (expand-file-name (cadr (rcd-crm-directory-data)) (rcd-crm-directory)) I have to improve various functions based on our conversation: This is for example not meant to be without slash on the end: (expand-file-name (cadr (rcd-crm-directory-data)) (rcd-crm-directory)) ⇒ "/home/data1/protected/hyperscope/3/5/5/8/2/By-ID" So there is work to do by using the function `file-name-as-directory' wherever directory is meant to be. Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-28 7:04 ` Jean Louis @ 2021-07-06 2:05 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-07-06 20:09 ` Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 2:05 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: > I have to improve various functions based on our > conversation: I still don't know how it should be done the right way, I also have a lot of URLs and hyperlinks, not the least in my my Emacs-w3m stuff https://dataswamp.org/~incal/emacs-init/w3m/ which I also don't know how they are supposed to look :) > I have to improve [...] > > Jean > > Take action in Free Software Foundation campaigns: > https://www.fsf.org/campaigns > > In support of Richard M. Stallman > https://stallmansupport.org/ Please improve this as well, RFC 3676, section 4.3 (Usenet Signature Convention) https://www.ietf.org/rfc/rfc3676.txt -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-07-06 2:05 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 20:09 ` Jean Louis 2021-07-06 20:23 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-07-06 20:09 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-07-06 05:11]: > Please improve this as well, > RFC 3676, section 4.3 (Usenet Signature Convention) > https://www.ietf.org/rfc/rfc3676.txt ohhhh.... I am sorry, did your Emacs segfault? -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-07-06 20:09 ` Jean Louis @ 2021-07-06 20:23 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-07-07 0:00 ` Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 20:23 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >> Please improve this as well, >> RFC 3676, section 4.3 (Usenet Signature Convention) >> https://www.ietf.org/rfc/rfc3676.txt > > ohhhh.... I am sorry, did your Emacs segfault? Well, to begin with, why do it the wrong way when it is so easy to do it the right way? Also, if you do it the wrong way configuration such as, in my case, `gnus-article-hide-signature' won't work. So it is not respectful of the people who don't want to see it and don't want to have to delete these lines every time they answer your posts. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-07-06 20:23 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-07 0:00 ` Jean Louis 0 siblings, 0 replies; 86+ messages in thread From: Jean Louis @ 2021-07-07 0:00 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-07-06 23:26]: > Jean Louis wrote: > > >> Please improve this as well, > >> RFC 3676, section 4.3 (Usenet Signature Convention) > >> https://www.ietf.org/rfc/rfc3676.txt > > > > ohhhh.... I am sorry, did your Emacs segfault? > > Well, to begin with, why do it the wrong way when it is so > easy to do it the right way? You are mistaken. My signatures are for majority of times the "right way", but rarely without -- > Also, if you do it the wrong way configuration such as, in my > case, `gnus-article-hide-signature' won't work. So it is not > respectful of the people who don't want to see it and don't > want to have to delete these lines every time they answer > your posts. I don't have a problem deleting whatever is remaining in the email, as I use the function `message-kill-to-signature' and I have it on the key binding. It is thus very easy to delete anything else not otherwise commented. It delets until my signature... so if there is your signature there without -- it will also get deleted without me even knowing it. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-26 6:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 7:15 ` Eli Zaretskii @ 2021-06-28 6:59 ` Jean Louis 2021-07-06 2:02 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-28 6:59 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg <moasenwood@zoho.eu> [2021-06-26 02:50]: > Jean Louis wrote: > > > To summarize, it is better to use file related functions > > whenever possible, checking if it is directory, using > > functions like `file-name-as-directory' and so on. > > Yes, of course. > > > (format "%s/%s/" (rcd-crm-directory-by-id) id)) > > (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) > > (concat (rcd-crm-directory) "/" (cadr (rcd-crm-directory-data)))) > > Is this what you are not allowed to do? > > I ask because it looks similar to mine, only not as good, > perhaps. Ha. > > OK, how is it suppose to look then? I think by using file- related functions: (defun doi-file-find (md5) "Return existing MD5 file for Double Opt-In.confirmation or NIL." (let ((file (concat (file-name-as-directory doi-directory) (file-name-as-directory (substring md5 0 doi-substring-to)) md5))) (if (file-exists-p file) file nil))) in that case `file-name-as-directory' is protecting the case of vraiable `doi-directory' not to have slash on the and. Before I have used my function: (defun slash-add (path) "Adds slash `/` quickly on the end of string" (if (string= path "") "/" (let ((last (substring (reverse path) 0 1))) (if (string= last "/") path (concat path "/"))))) Or (defun string-add (string add) "Returns string 'add' on the end of the string if there is none" (let* ((string (replace-regexp-in-string " *" "" string)) (added (string-match (format "%s$" add) string))) (if added string (concat string add)))) When concatenating directory names it is important to take care of slashes. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-28 6:59 ` Jean Louis @ 2021-07-06 2:02 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-07-06 20:06 ` Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 2:02 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >> OK, how is it suppose to look then? > > I think by using file- related functions: Well, yes, but I meant my stuff in particular: https://dataswamp.org/~incal/conf/.emacs > (defun doi-file-find (md5) > "Return existing MD5 file for Double Opt-In.confirmation > or NIL." Heh :) > (if (file-exists-p file) file nil))) (and (file-exists-p file) file) -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-07-06 2:02 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 20:06 ` Jean Louis 2021-07-06 20:20 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-07-06 20:06 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-07-06 05:06]: > > (if (file-exists-p file) file nil))) > > (and (file-exists-p file) file) I wasn't use to that form. But yes! -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-07-06 20:06 ` Jean Louis @ 2021-07-06 20:20 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-07-06 20:20 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >>> (if (file-exists-p file) file nil))) >> >> (and (file-exists-p file) file) > > I wasn't use to that form. But yes! Everyone should have a pal like me... -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 15:45 ` Jean Louis 2021-06-22 16:04 ` Eli Zaretskii @ 2021-06-26 6:41 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 6:41 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: >> We _represent_ file names as strings, but they are not >> normal strings. Just like characters are represented as >> integers, but they are not just simple integers, they have >> additional special attributes and behaviors. > > I get your point, what I don't agree with is the > Formulierung. It is for same reason as you mentioned it, > people are reading our writings and our form or text should > be possibly clear. If you wish to say they are not normal > strings, demonstrate it. By demonstration below it shows to > be of type string. What is else there? I don't know :) -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] 2021-06-22 12:37 ` Jean Louis 2021-06-22 13:10 ` Eli Zaretskii @ 2021-06-26 6:39 ` Emanuel Berg via Users list for the GNU Emacs text editor 1 sibling, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 6:39 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: > (type-of "/usr/bin/emacs") ; string > (type-of "/usr/bin/emacs-27.2") ; string > > Repeat after me: "The meaning of a string is not equal to > its type.." (require 'cl-lib) (setq denominator 1) ; 1 (cl-decf denominator) ; 0 (/ 1 denominator) ; Arithmetic error - oh, no! OK, lissen up guys - this does it! From now on, no more subtraction from integer denominators! This example shows the dangers of that. Please use `denominator-arithmetics' that will make sure the denominator isn't accidentally set to 0 before division. /Administration -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 12:45 ` Philip Kaludercic 2021-06-21 12:55 ` Eli Zaretskii 2021-06-21 14:11 ` tomas @ 2021-06-21 16:42 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 12:50 ` Lars Ingebrigtsen 3 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 16:42 UTC (permalink / raw) To: help-gnu-emacs Philip Kaludercic wrote: >> Why are you using 'format' where expand-file-name should >> be used? > > Does it really make a difference in a personal > configuration, especially when you don't use Windows or > other non /-delimiting systems? I knew it, this is some Windows thing, I can't say I care about Windows. BTW, are we even allowed to talk about Windows here or did they acquire a free software licence which I'm unaware of? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 12:45 ` Philip Kaludercic ` (2 preceding siblings ...) 2021-06-21 16:42 ` Emacs Modular Configuration: the preferable way Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 12:50 ` Lars Ingebrigtsen 2021-06-26 8:05 ` Emanuel Berg via Users list for the GNU Emacs text editor 3 siblings, 1 reply; 86+ messages in thread From: Lars Ingebrigtsen @ 2021-06-22 12:50 UTC (permalink / raw) To: Philip Kaludercic; +Cc: help-gnu-emacs Philip Kaludercic <philipk@posteo.net> writes: > Does it really make a difference in a personal configuration, especially > when you don't use Windows or other non /-delimiting systems? No, the code here is fine, and I think chiding people for writing perfectly find code is counterproductive. It's not what I'd put in a general library meant for redistribution, but nobody has any obligation to write code on any particular form for their own usage. Besides, `expand-file-name' has annoying corner cases, and Emacs should really grow a variation that's actually sound and reliable instead of the current DWIM-ish mess. For instance, the following loop might signal an error: (dolist (file (directory-files "/tmp/")) (unless (string-match "^/tmp" (expand-file-name file "/tmp")) (error "boom"))) while (dolist (file (directory-files "/tmp/")) (unless (string-match "^/tmp" (format "/tmp/%s" file)) (error "boom"))) never will. To see the difference, say $ touch "/tmp/~$USER" first. -- (domestic pets only, the antidote for overdose, milk.) bloggy blog: http://lars.ingebrigtsen.no ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-22 12:50 ` Lars Ingebrigtsen @ 2021-06-26 8:05 ` Emanuel Berg via Users list for the GNU Emacs text editor 0 siblings, 0 replies; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-26 8:05 UTC (permalink / raw) To: help-gnu-emacs Lars Ingebrigtsen wrote: >> Does it really make a difference in a personal >> configuration, especially when you don't use Windows or >> other non /-delimiting systems? > > No, the code here is fine, and I think chiding people for > writing perfectly find code is counterproductive. It's not > what I'd put in a general library meant for redistribution, > but nobody has any obligation to write code on any > particular form for their own usage. Yeah, however you write that from a position not just of highness but of vastness and interestingness, but to all the underground little devils that only have the accursed configuration file as an entry point to Lisp they might want to put it the right way in their code as well... Or the olympic athlete, it is more important that he does the pushups than the prisoner, right, because if the athlete doesn't do them, he'll loose the gold medal game, while if the prisoner doesn't do them, he'll loose his sanity... ? -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 2:56 ` Emanuel Berg via Users list for the GNU Emacs text editor ` (2 preceding siblings ...) 2021-06-21 11:29 ` Eli Zaretskii @ 2021-06-21 20:02 ` Jean Louis 2021-06-22 0:11 ` Emanuel Berg via Users list for the GNU Emacs text editor 3 siblings, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-21 20:02 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-06-21 05:57]: > (let ((emacs-init-files '( > abc.el > align-incal.el > batch.el > bibtex-incal.el > bike.el > bmi.el > buc.el > buffer-menu.el > caps-back.el > close.el > console-keys.el > count.el > custom-vars.el > day.el > dired-incal.el > ecat-incal.el > echo-message.el > edit.el > elpa.el > emacs-shell.el > face.el > file-write-to.el > file.el > fill-incal.el > frame-size.el > geh.el > get-search-string.el > help-incal.el > info-incal.el > isbn-verify.el > issn-verify.el > iterate-files.el > jean.el > keys.el > kill-path.el > kill.el > latex.el > lights.el > linux-shell.el > list-quoted-functions.el > man-incal.el > match-data-format.el > math.el > measure.el > minor-modes.el > misc.el > mode-by-filename.el > mode-line.el > navigate-fs-keys.el > negative-subtraction.el > perm.el > printer.el > quit.el > random.el > re-make-list.el > replace-list.el > revert-buffer.el > scale.el > scroll.el > search-regexp-in-files.el > sequence-string.el > shell-cli.el > show-command.el > signal.el > sort-incal.el > spell.el > street.el > string.el > sudo-user-path.el > super.el > survivor.el > switch-to-buffer-regexp.el > switch-to-buffer.el > tabs.el > test-face.el > test.el > time-cmp.el > time-incal.el > time-insert.el > todo-did.el > tramp-incal.el > variance.el > vt.el > window-incal.el > wood.el > wrap-search.el > xsel.el > yank.el > ))) > (dolist (f emacs-init-files) > (load-file (format "%s/%s" init-dir f) ))) You have many files to load and they are probably in different directories together with other files which are not to be loaded. I would then create a new directory and use key command `Y' from package `dired-x' to place symbolic link in the designated directory. In that directory I would have symbolic links of files that have to be loaded. If I don't need a file, I would remove symbolic link. The original file would be wherever it is. Then instead of having the long list there and updating it each time, I would use this: (mapc 'load-file (directory-files "~/.emacs.d/" t ".el$")) -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 20:02 ` Jean Louis @ 2021-06-22 0:11 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:19 ` Jean Louis 0 siblings, 1 reply; 86+ messages in thread From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:11 UTC (permalink / raw) To: help-gnu-emacs Jean Louis wrote: > You have many files to load and they are probably in > different directories That is evident from the code... > together with other files which are not to be loaded. That doesn't matter since every file that is to be loaded is mentioned explicitly. > Then instead of having the long list there and updating it > each time, I would use this: > > (mapc 'load-file (directory-files "~/.emacs.d/" t ".el$")) But then you can't do binary search on a file basis, like I said, which is a huge advantage, especially if you have a lot of source. -- underground experts united https://dataswamp.org/~incal ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-22 0:11 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-22 0:19 ` Jean Louis 0 siblings, 0 replies; 86+ messages in thread From: Jean Louis @ 2021-06-22 0:19 UTC (permalink / raw) To: help-gnu-emacs * Emanuel Berg via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> [2021-06-22 03:16]: > Jean Louis wrote: > > > You have many files to load and they are probably in > > different directories > > That is evident from the code... > > > together with other files which are not to be loaded. > > That doesn't matter since every file that is to be loaded is > mentioned explicitly. > > > Then instead of having the long list there and updating it > > each time, I would use this: > > > > (mapc 'load-file (directory-files "~/.emacs.d/" t ".el$")) > > But then you can't do binary search on a file basis, like > I said, which is a huge advantage, especially if you have > a lot of source. What is binary search on a file basis? -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 1:40 Emacs Modular Configuration: the preferable way Hongyi Zhao 2021-06-21 2:56 ` Emanuel Berg via Users list for the GNU Emacs text editor @ 2021-06-21 6:37 ` Jean Louis 2021-06-21 7:00 ` Hongyi Zhao 1 sibling, 1 reply; 86+ messages in thread From: Jean Louis @ 2021-06-21 6:37 UTC (permalink / raw) To: Hongyi Zhao; +Cc: help-gnu-emacs * Hongyi Zhao <hongyi.zhao@gmail.com> [2021-06-21 04:51]: > Dear all, > > I noticed the following instructions/tools for Emacs modular configuration: > > https://www.emacswiki.org/emacs/DotEmacsModular > https://www.emacswiki.org/emacs/DotEmacsStructuring > https://github.com/emacs-jp/init-loader > > There are so many ways to do this. What's the preferable way? Whatever you wish and want. You can feel if you need multiple files or not. Solutions are very individuals. -- Jean Take action in Free Software Foundation campaigns: https://www.fsf.org/campaigns In support of Richard M. Stallman https://stallmansupport.org/ ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 6:37 ` Jean Louis @ 2021-06-21 7:00 ` Hongyi Zhao 2021-06-21 10:06 ` Arthur Miller 0 siblings, 1 reply; 86+ messages in thread From: Hongyi Zhao @ 2021-06-21 7:00 UTC (permalink / raw) To: Hongyi Zhao, help-gnu-emacs On Mon, Jun 21, 2021 at 2:40 PM Jean Louis <bugs@gnu.support> wrote: > > * Hongyi Zhao <hongyi.zhao@gmail.com> [2021-06-21 04:51]: > > Dear all, > > > > I noticed the following instructions/tools for Emacs modular configuration: > > > > https://www.emacswiki.org/emacs/DotEmacsModular > > https://www.emacswiki.org/emacs/DotEmacsStructuring > > https://github.com/emacs-jp/init-loader > > > > There are so many ways to do this. What's the preferable way? > > Whatever you wish and want. You can feel if you need multiple files or > not. Solutions are very individuals. For now, my demand is as follows: 1. Use straight and use-package as the package manager. 2. All packages configuration file should call 1., especially for a testing scenario when debugging a package/several packages. 3. Better granular control based on different major mode, popular programming languages. Regards -- Assoc. Prof. Hongyi Zhao <hongyi.zhao@gmail.com> Theory and Simulation of Materials Hebei Vocational University of Technology and Engineering NO. 552 North Gangtie Road, Xingtai, China ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 7:00 ` Hongyi Zhao @ 2021-06-21 10:06 ` Arthur Miller 2021-06-21 10:26 ` Hongyi Zhao 0 siblings, 1 reply; 86+ messages in thread From: Arthur Miller @ 2021-06-21 10:06 UTC (permalink / raw) To: Hongyi Zhao; +Cc: help-gnu-emacs Hongyi Zhao <hongyi.zhao@gmail.com> writes: > On Mon, Jun 21, 2021 at 2:40 PM Jean Louis <bugs@gnu.support> wrote: >> >> * Hongyi Zhao <hongyi.zhao@gmail.com> [2021-06-21 04:51]: >> > Dear all, >> > >> > I noticed the following instructions/tools for Emacs modular configuration: >> > >> > https://www.emacswiki.org/emacs/DotEmacsModular >> > https://www.emacswiki.org/emacs/DotEmacsStructuring >> > https://github.com/emacs-jp/init-loader >> > >> > There are so many ways to do this. What's the preferable way? >> >> Whatever you wish and want. You can feel if you need multiple files or >> not. Solutions are very individuals. > > For now, my demand is as follows: > > 1. Use straight and use-package as the package manager. Why? Some special reason? > 2. All packages configuration file should call 1., especially for a > testing scenario when debugging a package/several packages. Why? Just for sake of calling it or you have some better reason? > 3. Better granular control based on different major mode, popular > programming languages. > You don't need straight, nor any special package for this, it is how you structure your code. Check here, granularity is per package (mostly): https://github.com/amno1/.emacs.d/blob/main/init.org Nothing external required, just built-in stuff that comes out of the box. Package.el is used to fetch packages from elpa/melpa and few simple macros to save some typing, not even use-package needed and I think it is pretty structured init file. I can even configure early-init.el as it was a hook, which lets me structure entire init process in one place. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 10:06 ` Arthur Miller @ 2021-06-21 10:26 ` Hongyi Zhao 2021-06-21 11:10 ` Arthur Miller 0 siblings, 1 reply; 86+ messages in thread From: Hongyi Zhao @ 2021-06-21 10:26 UTC (permalink / raw) To: Arthur Miller; +Cc: help-gnu-emacs On Mon, Jun 21, 2021 at 6:06 PM Arthur Miller <arthur.miller@live.com> wrote: > > Hongyi Zhao <hongyi.zhao@gmail.com> writes: > > > On Mon, Jun 21, 2021 at 2:40 PM Jean Louis <bugs@gnu.support> wrote: > >> > >> * Hongyi Zhao <hongyi.zhao@gmail.com> [2021-06-21 04:51]: > >> > Dear all, > >> > > >> > I noticed the following instructions/tools for Emacs modular configuration: > >> > > >> > https://www.emacswiki.org/emacs/DotEmacsModular > >> > https://www.emacswiki.org/emacs/DotEmacsStructuring > >> > https://github.com/emacs-jp/init-loader > >> > > >> > There are so many ways to do this. What's the preferable way? > >> > >> Whatever you wish and want. You can feel if you need multiple files or > >> not. Solutions are very individuals. > > > > For now, my demand is as follows: > > > > 1. Use straight and use-package as the package manager. > > Why? Some special reason? For working/dealing with all packages, regardless that they are hosted by Emacs package repos or not. Straight works with git perfectly, and at the same time, it is also seamlessly integrates with use-package. > > > 2. All packages configuration file should call 1., especially for a > > testing scenario when debugging a package/several packages. > > Why? Just for sake of calling it or you have some better reason? Same as above. > > > 3. Better granular control based on different major mode, popular > > programming languages. > > > > You don't need straight, nor any special package for this, it is how > you structure your code. Check here, granularity is per package (mostly): > > https://github.com/amno1/.emacs.d/blob/main/init.org > > Nothing external required, just built-in stuff that comes out of the > box. Package.el is used to fetch packages from elpa/melpa and few > simple macros to save some typing, not even use-package needed and I > think it is pretty structured init file. I can even configure > early-init.el as it was a hook, which lets me structure entire init > process in one place. From my experience, package.el's package fetch mechanism/speed is fragile and very poor by comparison with straight. Regards -- Assoc. Prof. Hongyi Zhao <hongyi.zhao@gmail.com> Theory and Simulation of Materials Hebei Vocational University of Technology and Engineering NO. 552 North Gangtie Road, Xingtai, China ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 10:26 ` Hongyi Zhao @ 2021-06-21 11:10 ` Arthur Miller 2021-06-23 2:17 ` Hongyi Zhao 0 siblings, 1 reply; 86+ messages in thread From: Arthur Miller @ 2021-06-21 11:10 UTC (permalink / raw) To: Hongyi Zhao; +Cc: help-gnu-emacs Hongyi Zhao <hongyi.zhao@gmail.com> writes: > On Mon, Jun 21, 2021 at 6:06 PM Arthur Miller <arthur.miller@live.com> wrote: >> >> Hongyi Zhao <hongyi.zhao@gmail.com> writes: >> >> > On Mon, Jun 21, 2021 at 2:40 PM Jean Louis <bugs@gnu.support> wrote: >> >> >> >> * Hongyi Zhao <hongyi.zhao@gmail.com> [2021-06-21 04:51]: >> >> > Dear all, >> >> > >> >> > I noticed the following instructions/tools for Emacs modular configuration: >> >> > >> >> > https://www.emacswiki.org/emacs/DotEmacsModular >> >> > https://www.emacswiki.org/emacs/DotEmacsStructuring >> >> > https://github.com/emacs-jp/init-loader >> >> > >> >> > There are so many ways to do this. What's the preferable way? >> >> >> >> Whatever you wish and want. You can feel if you need multiple files or >> >> not. Solutions are very individuals. >> > >> > For now, my demand is as follows: >> > >> > 1. Use straight and use-package as the package manager. >> >> Why? Some special reason? > > For working/dealing with all packages, regardless that they are hosted > by Emacs package repos or not. Straight works with git perfectly, and Which opens for a vulnerability which was discussed on emacs-help some few months ago. Of course it is your personal choice what you will download and use, but I would be very careful to just download stuff from git without looking at it first. >> Why? Just for sake of calling it or you have some better reason? > > Same as above. I get that "granularity" you speak above without need for 3k+ lines of code :). >> >> > 3. Better granular control based on different major mode, popular >> > programming languages. >> > >> >> You don't need straight, nor any special package for this, it is how >> you structure your code. Check here, granularity is per package (mostly): >> >> https://github.com/amno1/.emacs.d/blob/main/init.org >> >> Nothing external required, just built-in stuff that comes out of the >> box. Package.el is used to fetch packages from elpa/melpa and few >> simple macros to save some typing, not even use-package needed and I >> think it is pretty structured init file. I can even configure >> early-init.el as it was a hook, which lets me structure entire init >> process in one place. > > From my experience, package.el's package fetch mechanism/speed is > fragile and very poor by comparison > with straight. Really? Does straight.el implemnt it's own network stack? I thought it uses Emacs facilities, same as package.el. Do you have any numbers to back up your opinion? Since you are so experienced and already have made your mind I don't see the point of even asking. Especially since author of package.el have already done all the "thinking" for you, at least as he puts it on the project page: "straight.el frees you from needing to think about package management, since I already did all the thinking to figure how best to design everything." :D I just have no comments on that one. ^ permalink raw reply [flat|nested] 86+ messages in thread
* Re: Emacs Modular Configuration: the preferable way. 2021-06-21 11:10 ` Arthur Miller @ 2021-06-23 2:17 ` Hongyi Zhao 0 siblings, 0 replies; 86+ messages in thread From: Hongyi Zhao @ 2021-06-23 2:17 UTC (permalink / raw) To: Arthur Miller; +Cc: help-gnu-emacs On Mon, Jun 21, 2021 at 7:11 PM Arthur Miller <arthur.miller@live.com> wrote: > > Hongyi Zhao <hongyi.zhao@gmail.com> writes: > > > On Mon, Jun 21, 2021 at 6:06 PM Arthur Miller <arthur.miller@live.com> wrote: > >> > >> Hongyi Zhao <hongyi.zhao@gmail.com> writes: > >> > >> > On Mon, Jun 21, 2021 at 2:40 PM Jean Louis <bugs@gnu.support> wrote: > >> >> > >> >> * Hongyi Zhao <hongyi.zhao@gmail.com> [2021-06-21 04:51]: > >> >> > Dear all, > >> >> > > >> >> > I noticed the following instructions/tools for Emacs modular configuration: > >> >> > > >> >> > https://www.emacswiki.org/emacs/DotEmacsModular > >> >> > https://www.emacswiki.org/emacs/DotEmacsStructuring > >> >> > https://github.com/emacs-jp/init-loader > >> >> > > >> >> > There are so many ways to do this. What's the preferable way? > >> >> > >> >> Whatever you wish and want. You can feel if you need multiple files or > >> >> not. Solutions are very individuals. > >> > > >> > For now, my demand is as follows: > >> > > >> > 1. Use straight and use-package as the package manager. > >> > >> Why? Some special reason? > > > > For working/dealing with all packages, regardless that they are hosted > > by Emacs package repos or not. Straight works with git perfectly, and > > Which opens for a vulnerability which was discussed on emacs-help some > few months ago. Of course it is your personal choice what you will > download and use, but I would be very careful to just download stuff > from git without looking at it first. > > >> Why? Just for sake of calling it or you have some better reason? > > > > Same as above. > > I get that "granularity" you speak above without need for 3k+ lines of > code :). > > >> > >> > 3. Better granular control based on different major mode, popular > >> > programming languages. > >> > > >> > >> You don't need straight, nor any special package for this, it is how > >> you structure your code. Check here, granularity is per package (mostly): > >> > >> https://github.com/amno1/.emacs.d/blob/main/init.org > >> > >> Nothing external required, just built-in stuff that comes out of the > >> box. Package.el is used to fetch packages from elpa/melpa and few > >> simple macros to save some typing, not even use-package needed and I > >> think it is pretty structured init file. I can even configure > >> early-init.el as it was a hook, which lets me structure entire init > >> process in one place. > > > > From my experience, package.el's package fetch mechanism/speed is > > fragile and very poor by comparison > > with straight. > > Really? Does straight.el implemnt it's own network stack? I thought it > uses Emacs facilities, same as package.el. Do you have any numbers to > back up your opinion? TBF, no. Just out of limited intuition. To a large extent, I could be wrong. As you've told, it only relies on git for network operations. HY > > Since you are so experienced and already have made your mind I don't see > the point of even asking. Especially since author of package.el have > already done all the "thinking" for you, at least as he puts it on the > project page: > > "straight.el frees you from needing to think about package management, > since I already did all the thinking to figure how best to design > everything." > > :D I just have no comments on that one. > -- Assoc. Prof. Hongyi Zhao <hongyi.zhao@gmail.com> Theory and Simulation of Materials Hebei Vocational University of Technology and Engineering NO. 552 North Gangtie Road, Xingtai, China ^ permalink raw reply [flat|nested] 86+ messages in thread
end of thread, other threads:[~2021-07-07 0:00 UTC | newest] Thread overview: 86+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2021-06-21 1:40 Emacs Modular Configuration: the preferable way Hongyi Zhao 2021-06-21 2:56 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 6:40 ` Jean Louis 2021-06-21 16:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 19:55 ` Jean Louis 2021-06-22 0:06 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 10:14 ` Arthur Miller 2021-06-21 16:40 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:25 ` [External] : " Drew Adams 2021-06-26 0:17 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 0:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:38 ` Arthur Miller 2021-06-22 0:03 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:17 ` Jean Louis 2021-06-22 7:52 ` Arthur Miller 2021-06-26 6:58 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 11:29 ` Eli Zaretskii 2021-06-21 12:45 ` Philip Kaludercic 2021-06-21 12:55 ` Eli Zaretskii 2021-06-21 13:59 ` [External] : " Drew Adams 2021-06-21 16:51 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:08 ` Eli Zaretskii 2021-06-21 18:26 ` FW: " Drew Adams 2021-06-26 0:06 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 14:11 ` tomas 2021-06-21 16:47 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 18:06 ` Eli Zaretskii 2021-06-21 21:09 ` Jean Louis 2021-06-22 11:45 ` Eli Zaretskii 2021-06-22 12:29 ` Jean Louis 2021-06-22 13:07 ` Eli Zaretskii 2021-06-21 20:05 ` Stefan Monnier via Users list for the GNU Emacs text editor 2021-06-22 0:16 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 21:07 ` Jean Louis 2021-06-22 0:33 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:52 ` Printf and quoting in general, SQL injection in particular Jean Louis 2021-06-26 6:50 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 7:30 ` Yuri Khan 2021-06-26 7:57 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 9:37 ` tomas 2021-06-28 7:02 ` Jean Louis 2021-07-06 2:12 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-07-06 2:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 20:36 ` Emacs Modular Configuration: the preferable way Jean Louis 2021-06-21 21:15 ` Printf and quoting in general, SQL injection in particular [was: Emacs Modular Configuration: the preferable way] tomas 2021-06-21 21:29 ` Jean Louis 2021-06-22 0:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:47 ` Jean Louis 2021-06-26 6:31 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-28 6:56 ` Jean Louis 2021-07-06 1:57 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-07-06 20:04 ` Jean Louis 2021-07-06 20:19 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:23 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 12:12 ` Eli Zaretskii 2021-06-22 12:37 ` Jean Louis 2021-06-22 13:10 ` Eli Zaretskii 2021-06-22 15:45 ` Jean Louis 2021-06-22 16:04 ` Eli Zaretskii 2021-06-22 18:01 ` Jean Louis 2021-06-22 18:25 ` Eli Zaretskii 2021-06-26 6:46 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 7:15 ` Eli Zaretskii 2021-06-28 7:04 ` Jean Louis 2021-07-06 2:05 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-07-06 20:09 ` Jean Louis 2021-07-06 20:23 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-07-07 0:00 ` Jean Louis 2021-06-28 6:59 ` Jean Louis 2021-07-06 2:02 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-07-06 20:06 ` Jean Louis 2021-07-06 20:20 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 6:41 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-26 6:39 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 16:42 ` Emacs Modular Configuration: the preferable way Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 12:50 ` Lars Ingebrigtsen 2021-06-26 8:05 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-21 20:02 ` Jean Louis 2021-06-22 0:11 ` Emanuel Berg via Users list for the GNU Emacs text editor 2021-06-22 0:19 ` Jean Louis 2021-06-21 6:37 ` Jean Louis 2021-06-21 7:00 ` Hongyi Zhao 2021-06-21 10:06 ` Arthur Miller 2021-06-21 10:26 ` Hongyi Zhao 2021-06-21 11:10 ` Arthur Miller 2021-06-23 2:17 ` Hongyi Zhao
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).