emacs sql mode could not save history - sql

below is my settings:
(defun my-sql-save-history-hook ()
(let ((lval 'sql-input-ring-file-name)
(rval 'sql-product))
(if (symbol-value rval)
(let ((filename
(concat "~/.emacs.d/sql/"
(symbol-name (symbol-value rval))
"-history.sql")))
(set (make-local-variable lval) filename)
(set-default 'sql-input-ring-file-name filename))
(error
(format "SQL history will not be saved because %s is nil"
(symbol-name rval))))))
and i describe the variable values:
sql-input-ring-file-name's value is
"~/.emacs.d/sql/mysql-history.sql"
Original value was nil
Local in buffer *SQL*; global value is the same.
and i have directory ~/.emacs.d/sql but do not have any file
my emacs version is 24.4.1

I had trouble getting the answers above to work, but this works for me. The main change is lval and kill-buffer-hook
(defun my-sql-save-history-hook ()
(let ((lval 'comint-input-ring-file-name)
(rval 'sql-product))
(if (symbol-value rval)
(let ((filename
(concat "~/.emacs.d/sql/"
(symbol-name (symbol-value rval))
"-history.sql")))
(set (make-local-variable lval) filename))
(error
(format "SQL history will not be saved because %s is nil"
(symbol-name rval))))))
(add-hook 'sql-interactive-mode-hook 'my-sql-save-history-hook)
(add-hook 'kill-buffer-hook 'comint-write-input-ring)

Related

Processing SQL Queries as Lazy Streams in Racket

Language: Racket (with SQL query code/pointer)
Libraries: db, racket/stream, racket/sequence
Goal: lazily process the value of sql queries using streams in Racket.
Question 1: how do you manipulate SQL query stream objects in Racket? (I can get the stream-first value of the stream but not the rest of the stream!)
#lang racket/base
(require db
racket/sequence
racket/stream)
(define db_sql_local
(mysql-connect
#:user "<my-username>"
#:database "<my-database>"
#:server "<my-server>"
#:port <my-port>
#:password "<my-password>"))
;; PROBLEM 1 HERE
(define test-stream
(sequence->stream
(in-query
chembl_sql_local
"SELECT * FROM <table-name>"
#:fetch +inf.0)))
(stream-first test-stream)
;; stream-first of test-stream returns the first-row of the table as a '(#vector).
Any advice or comments would be greatly appreciated - Thank you!
First, the sequence returned by in-query does not contain vectors; each "element" of the sequence contains multiple values, one per column returned. See the paragraph in the Sequence docs starting "Individual elements of a sequence..." about multiple-valued elements.
Second, using #:fetch +inf.0 (the default behavior) means that all rows are fetched before the sequence is returned. So there's nothing lazy about the code above; you could use query-rows instead and get a list, which would be easier to work with (and query-rows does represent each row as a vector).
Finally, use stream-rest to get the rest of a stream. For example:
(require db racket/stream racket/sequence)
(define c (sqlite3-connect #:database 'memory))
(define qseq (in-query c "SELECT 1, 2 UNION SELECT 3, 4" #:fetch 1))
qseq
;; => #<sequence>
(define qstream (sequence->stream qseq))
qstream
;; => #<stream>
(stream-first qstream)
;; => 1 2
(stream-rest qstream)
;; => #<stream>
(stream-first (stream-rest qstream))
;; => 3 4
thanks for your quick reply. The #:fetch 1 arg was definitely what I was looking for to make it lazy. I've attached updated code that should lazily stream sql queries to export tsv files.
(define sql_server
(mysql-connect
#:user <username>
#:database <db-name>
#:server <server>
#:port <port-num>
#:password <password>))
(define query-->stream
(lambda (db-conn query)
(sequence->stream
(in-query
db-conn
query
#:fetch 1))))
(define print-table-row-to-tsv
(lambda (ls port)
(cond
((null? ls)
(fprintf port "~c" #\newline)
(void))
((sql-null? (car ls))
(fprintf port "~a~c" "NULL" #\tab)
(print-table-row-to-tsv (cdr ls) port))
((null? (cdr ls))
(fprintf port "~a" (car ls))
(print-table-row-to-tsv (cdr ls) port))
(else
(fprintf port "~a~c" (car ls) #\tab)
(print-table-row-to-tsv (cdr ls) port)))))
(define get-table-col-names
(lambda (db-conn tbl-name)
(map (lambda (x) (vector-ref x 0))
(query-rows db-conn (string-append "DESCRIBE " tbl-name)))))
(define export-query-result-to-tsv
(lambda (db-conn tbl-name query)
(let* ((tbl-col-names (get-table-col-names db-conn tbl-name))
(output-file (open-output-file (format "~achembl_~a_table.tsv" (find-system-path 'home-dir) tbl-name) #:exists 'replace))
(stream (query-->stream db-conn query)))
(begin
(print-table-row-to-tsv tbl-col-names output-file)
(process-stream-to-tsv stream output-file)
(close-output-port output-file)))))
(define process-stream-to-tsv
(lambda (stream port)
(cond
((stream-empty? stream)
(void))
(else
(begin
(print-table-row-to-tsv (call-with-values (lambda () (stream-first stream)) list) port)
(process-stream-to-tsv (stream-rest stream) port))))))
(export-query-result-to-tsv sql_server "<table-name>" "SELECT * FROM <table-name>;")

'Symbol's value as variable is void:' when using parameter on defun inside lambda

I would like to make this function to set keybind more shorter.
(defun defkey-arg2 ()
(exwm-input-set-key (kbd "s-g")
(lambda ()
(interactive)
(start-process-shell-command gkamus nil gkamus))))
then I write the shorter function with 2 parameters (the keybind and the app name)
(defun defkey-arg2 (key command) (...)
When I try the key as parameter, it will work
(defun defkey-arg2 (key)
(exwm-input-set-key (kbd key)
(lambda ()
(interactive)
(start-process-shell-command gkamus nil gkamus))))
(defkey-arg2 "s-g")
But, when I try write function like this
(defun defkey-arg2 (key command)
or
(defun defkey-arg2 (command)
(exwm-input-set-key (kbd "s-g")
(lambda ()
(interactive)
(start-process-shell-command command nil command)))
(defkey-arg2 "gkamus")
it raises error:
Symbol's value as variable is void:' when using parameter on defun
The body of lambda isn't evaluated. Using a backquote, the value of command can be substituted into the resulting expression.
(defun defkey-arg2 (command)
(define-key (current-local-map)
(kbd "s-g")
`(lambda ()
(interactive)
(start-process-shell-command ,command nil ,command))))

How to correctly use setq in elisp?

In my emacs config I try to configure the project root for jedi using the following code:
(setq jedi:server-args '("--sys-path" (projectile-project-root)))
Which throws a:
deferred error : (wrong-type-argument stringp (projectile-project-root))
(I have (setq debug-on-error t) but the backtrace shows nothing)
If I hardcode the path like this all works as expected:
(setq jedi:server-args '("--sys-path" "/some/path"))
To give this line some context, here's the surrounding code:
(add-hook 'python-mode-hook 'jedi:setup)
(setq debug-on-error t)
(defun jedi-config:setup-server-args ()
(message (format "Configuring current project dir: %s"
(projectile-project-root)))
(setq jedi:server-args '("--sys-path" (projectile-project-root))))
(add-hook 'python-mode-hook
'jedi-config:setup-server-args)
How can I set the server-args for jedi using the projectile variable?
I finally figured it out - rather simple really:
(setq jedi:server-args (list "--sys-path" (projectile-project-root)))

How to load non-standard characters from file using SBCL Common Lisp? [duplicate]

This question already has an answer here:
How to handle accents in Common Lisp (SBCL)?
(1 answer)
Closed 6 years ago.
Trying
loading contents of file containing one line with word: λέξη
(with-open-file (s PATH-TO-FILE :direction :input)
(let ((a (read-line s)))
(print a)))
outputs
""
T
Trying:
(with-open-file (s PATH-TO-FILE :direction :input)
(let ((buffer ""))
(do ((character (read-char s nil) (read-char s nil)))
((null character))
(setf buffer (concatenate 'string buffer (format nil "~a" character))))
(format t "~a" buffer)))
outputs
funny characters (nothing like the original contents)
T
What I would like to do is to load all lines of file containing such non-standard characters.
Then I want to be able to output these words to console or via LTK widgets (text on button for example).
You need to pass :external-format X to with-open-file, where
X is the actual encoding used in the file (:utf-8 or :ISO-8859-7 or whatever).
(with-open-file (stream PATH-TO-FILE :external-format :utf-8)
(let ((line (read-line stream)))
(loop :for char :across line :do
(print (list (char-name char) (char-code char))))
line))
Since it prints
("ZERO_WIDTH_NO-BREAK_SPACE" 65279)
("GREEK_SMALL_LETTER_LAMDA" 955)
("GREEK_SMALL_LETTER_EPSILON_WITH_TONOS" 941)
("GREEK_SMALL_LETTER_XI" 958)
("GREEK_SMALL_LETTER_ETA" 951)
you can see that you are, indeed, reading the file correctly.
Your problem now if how to print those non-ASCII characters to the screen, and that is an entirely different question.

Switching buffers between header/implementation in emacs in obj-c (obj-c++) mode

How do I make emacs switch between buffers with header/implementation files in obj-c (c++) mode (that is, between foo.[mM]{1,2} and foo.[hH]{1,2})? Is it possible to assign standard Xcode keyboard shortcut (ctrl+cmd) for running such a macro?
Emacs has built-in support for jumping from header file to implementation file using ff-find-other-file:
(add-hook 'c-mode-common-hook
(lambda()
(local-set-key (kbd "C-c m d") 'ff-find-other-file)))
CC mode includes C, C++, Java, Objective C, etc.
Have a look at this link. He describes this function:
(defun objc-in-header-file ()
(let* ((filename (buffer-file-name))
(extension (car (last (split-string filename "\\.")))))
(string= "h" extension)))
(defun objc-jump-to-extension (extension)
(let* ((filename (buffer-file-name))
(file-components (append (butlast (split-string filename
"\\."))
(list extension))))
(find-file (mapconcat 'identity file-components "."))))
;;; Assumes that Header and Source file are in same directory
(defun objc-jump-between-header-source ()
(interactive)
(if (objc-in-header-file)
(objc-jump-to-extension "m")
(objc-jump-to-extension "h")))
(defun objc-mode-customizations ()
(define-key objc-mode-map (kbd "C-c t") 'objc-jump-between-header-source))
(add-hook 'objc-mode-hook 'objc-mode-customizations)
It's possible to extend the eassist-switch-h-cpp function from CEDET's contrib to work with ObjC files, in addition to C/C++ code. The change is simple, add following code to your init file:
(eval-after-load "eassist"
'(progn
(setq eassist-header-switches '(("h" . ("cpp" "cc" "c" "m"))
("hpp" . ("cpp" "cc"))
("cpp" . ("h" "hpp"))
("c" . ("h"))
("m" . ("h"))
("C" . ("H"))
("H" . ("C" "CPP" "CC"))
("cc" . ("h" "hpp"))))))
and you can call the eassist-swith-h-cpp function - it will handle switching between header and implementation files. And you may bound this function to selected key (C-c t in given hook):
(defun my/c-mode-cedet-hook ()
(local-set-key "\C-ct" 'eassist-switch-h-cpp))
(add-hook 'c-mode-common-hook 'my/c-mode-cedet-hook)