summaryrefslogtreecommitdiff
path: root/lisp/progmodes
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes')
-rw-r--r--lisp/progmodes/cc-engine.el58
-rw-r--r--lisp/progmodes/cc-mode.el2
-rw-r--r--lisp/progmodes/cc-vars.el4
-rw-r--r--lisp/progmodes/sql.el193
4 files changed, 222 insertions, 35 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 071efbc55b5..27ce3029c4a 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -1732,6 +1732,7 @@ comment at the start of cc-engine.el for more info."
(put-text-property beg end 'c-is-sws t)
,@(when (facep 'c-debug-is-sws-face)
'((c-debug-add-face beg end 'c-debug-is-sws-face)))))
+(def-edebug-spec c-put-is-sws t)
(defmacro c-put-in-sws (beg end)
;; This macro does a hidden buffer change.
@@ -1739,6 +1740,7 @@ comment at the start of cc-engine.el for more info."
(put-text-property beg end 'c-in-sws t)
,@(when (facep 'c-debug-is-sws-face)
'((c-debug-add-face beg end 'c-debug-in-sws-face)))))
+(def-edebug-spec c-put-in-sws t)
(defmacro c-remove-is-sws (beg end)
;; This macro does a hidden buffer change.
@@ -1746,6 +1748,7 @@ comment at the start of cc-engine.el for more info."
(remove-text-properties beg end '(c-is-sws nil))
,@(when (facep 'c-debug-is-sws-face)
'((c-debug-remove-face beg end 'c-debug-is-sws-face)))))
+(def-edebug-spec c-remove-is-sws t)
(defmacro c-remove-in-sws (beg end)
;; This macro does a hidden buffer change.
@@ -1753,6 +1756,7 @@ comment at the start of cc-engine.el for more info."
(remove-text-properties beg end '(c-in-sws nil))
,@(when (facep 'c-debug-is-sws-face)
'((c-debug-remove-face beg end 'c-debug-in-sws-face)))))
+(def-edebug-spec c-remove-in-sws t)
(defmacro c-remove-is-and-in-sws (beg end)
;; This macro does a hidden buffer change.
@@ -1761,6 +1765,7 @@ comment at the start of cc-engine.el for more info."
,@(when (facep 'c-debug-is-sws-face)
'((c-debug-remove-face beg end 'c-debug-is-sws-face)
(c-debug-remove-face beg end 'c-debug-in-sws-face)))))
+(def-edebug-spec c-remove-is-and-in-sws t)
;; The type of literal position `end' is in a `before-change-functions'
;; function - one of `c', `c++', `pound', or nil (but NOT `string').
@@ -1769,12 +1774,14 @@ comment at the start of cc-engine.el for more info."
;; enclosing END, if any, else nil.
(defvar c-sws-lit-limits nil)
-(defun c-invalidate-sws-region-before (end)
- ;; Called from c-before-change. END is the end of the change region, the
- ;; standard parameter given to all before-change-functions.
+(defun c-invalidate-sws-region-before (beg end)
+ ;; Called from c-before-change. BEG and END are the bounds of the change
+ ;; region, the standard parameters given to all before-change-functions.
;;
- ;; Note whether END is inside a comment or CPP construct, and if so note its
- ;; bounds in `c-sws-lit-limits' and type in `c-sws-lit-type'.
+ ;; Note whether END is inside a comment, CPP construct, or noise macro, and
+ ;; if so note its bounds in `c-sws-lit-limits' and type in `c-sws-lit-type'.
+ (setq c-sws-lit-type nil
+ c-sws-lit-limits nil)
(save-excursion
(goto-char end)
(let* ((limits (c-literal-limits))
@@ -1787,8 +1794,19 @@ comment at the start of cc-engine.el for more info."
(setq c-sws-lit-type 'pound
c-sws-lit-limits (cons (point)
(progn (c-end-of-macro) (point)))))
- (t (setq c-sws-lit-type nil
- c-sws-lit-limits nil))))))
+ ((progn (skip-syntax-backward "w_")
+ (looking-at c-noise-macro-name-re))
+ (setq c-sws-lit-type 'noise
+ c-sws-lit-limits (cons (match-beginning 1) (match-end 1))))
+ (t))))
+ (save-excursion
+ (goto-char beg)
+ (skip-syntax-backward "w_")
+ (when (looking-at c-noise-macro-name-re)
+ (setq c-sws-lit-type 'noise)
+ (if (consp c-sws-lit-limits)
+ (setcar c-sws-lit-limits (match-beginning 1))
+ (setq c-sws-lit-limits (cons (match-beginning 1) (match-end 1)))))))
(defun c-invalidate-sws-region-after-del (beg end old-len)
;; Text has been deleted, OLD-LEN characters of it starting from position
@@ -1797,7 +1815,6 @@ comment at the start of cc-engine.el for more info."
;; deletion deleted or "damaged" its opening delimiter. If so, return the
;; current position of where the construct ended, otherwise return nil.
(when c-sws-lit-limits
- (setcdr c-sws-lit-limits (- (cdr c-sws-lit-limits) old-len))
(if (and (< beg (+ (car c-sws-lit-limits) 2)) ; A lazy assumption that
; comment delimiters are 2
; chars long.
@@ -1815,9 +1832,9 @@ comment at the start of cc-engine.el for more info."
;; or `c-is-sws' text properties inside this literal. If there are, return
;; the buffer position of the end of the literal, else return nil.
(save-excursion
+ (goto-char end)
(let* ((limits (c-literal-limits))
(lit-type (c-literal-type limits)))
- (goto-char end)
(when (and (not (memq lit-type '(c c++)))
(c-beginning-of-macro))
(setq lit-type 'pound
@@ -1841,6 +1858,10 @@ comment at the start of cc-engine.el for more info."
;; properties right after they're added.
;;
;; This function does hidden buffer changes.
+ (when c-sws-lit-limits
+ (setcar c-sws-lit-limits (min beg (car c-sws-lit-limits)))
+ (setcdr c-sws-lit-limits
+ (max end (- (+ (cdr c-sws-lit-limits) (- end beg)) old-len))))
(let ((del-end
(and (> old-len 0)
(c-invalidate-sws-region-after-del beg end old-len)))
@@ -1860,6 +1881,10 @@ comment at the start of cc-engine.el for more info."
(when (and (eolp) (not (eobp)))
(setq end (1+ (point)))))
+ (when (eq c-sws-lit-type 'noise)
+ (setq beg (car c-sws-lit-limits)
+ end (cdr c-sws-lit-limits))) ; This last setting may be redundant.
+
(when (and (= beg end)
(get-text-property beg 'c-in-sws)
(> beg (point-min))
@@ -1879,6 +1904,7 @@ comment at the start of cc-engine.el for more info."
(setq end (max (or del-end end)
(or ins-end end)
+ (or (cdr c-sws-lit-limits) end)
end))
(c-debug-sws-msg "c-invalidate-sws-region-after [%s..%s]" beg end)
@@ -2147,7 +2173,8 @@ comment at the start of cc-engine.el for more info."
;; Try to find a rung position in the simple ws preceding point, so that
;; we can get a cache hit even if the last bit of the simple ws has
;; changed recently.
- (setq simple-ws-beg (point))
+ (setq simple-ws-beg (or (match-end 1) ; Noise macro
+ (match-end 0))) ; c-syntactic-ws-end
(skip-chars-backward " \t\n\r\f\v")
(if (setq rung-is-marked (text-property-any
(point) (min (1+ rung-pos) (point-max))
@@ -8672,7 +8699,16 @@ comment at the start of cc-engine.el for more info."
(not (and (c-major-mode-is 'c-mode)
(not got-prefix)
(or (eq context 'top) make-top)
- (eq (char-after) ?\)))))
+ (eq (char-after) ?\))
+ (or (memq at-type '(nil maybe))
+ (not got-identifier)
+ (save-excursion
+ (goto-char after-paren-pos)
+ (c-forward-syntactic-ws)
+ ;; Prevent the symbol being recorded as a type.
+ (let (c-record-type-identifiers)
+ (not (memq (c-forward-type)
+ '(nil maybe)))))))))
(if (eq (char-after) ?\))
(when (> paren-depth 0)
(setq paren-depth (1- paren-depth))
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index a2ad07fddb0..6718813b79c 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1623,7 +1623,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"?
(when (< beg end)
(c-unfind-coalesced-tokens beg end))
- (c-invalidate-sws-region-before end)
+ (c-invalidate-sws-region-before beg end)
;; Are we (potentially) disrupting the syntactic context which
;; makes a type a type? E.g. by inserting stuff after "foo" in
;; "foo bar;", or before "foo" in "typedef foo *bar;"?
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 66960b630e1..89534882672 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -1649,7 +1649,9 @@ white space either before or after the operator, but not both."
;; Initialize the next two to a regexp which never matches.
(defvar c-noise-macro-with-parens-name-re "a\\`")
+(make-variable-buffer-local 'c-noise-macro-with-parens-name-re)
(defvar c-noise-macro-name-re "a\\`")
+(make-variable-buffer-local 'c-noise-macro-name-re)
(defcustom c-noise-macro-names nil
"A list of names of macros which expand to nothing, or compiler extensions
@@ -1664,6 +1666,7 @@ this implicitly by reinitializing C/C++/Objc Mode on any buffer)."
:type '(repeat :tag "List of names" string)
:group 'c)
(put 'c-noise-macro-names 'safe-local-variable #'c-string-list-p)
+(make-variable-buffer-local 'c-noise-macro-names)
(defcustom c-noise-macro-with-parens-names nil
"A list of names of macros \(or compiler extensions like \"__attribute__\")
@@ -1673,6 +1676,7 @@ These are recognized by CC Mode only in declarations."
:type '(repeat :tag "List of names (possibly empty)" string)
:group 'c)
(put 'c-noise-macro-with-parens-names 'safe-local-variable #'c-string-list-p)
+(make-variable-buffer-local 'c-noise-macro-with-parens-names)
(defun c-make-noise-macro-regexps ()
;; Convert `c-noise-macro-names' and `c-noise-macro-with-parens-names' into
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 6ad221295ca..9bae3d86640 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -237,6 +237,7 @@
(require 'custom)
(require 'thingatpt)
(require 'view)
+(eval-when-compile (require 'subr-x)) ; string-empty-p
(defvar font-lock-keyword-face)
(defvar font-lock-set-defaults)
@@ -738,16 +739,131 @@ The package must be available to be loaded and activated."
:type 'booleanp
:version "27.1")
-(defun sql-is-indent-available ()
- "Check if sql-indent module is available."
- (when (locate-library "sql-indent")
- (fboundp 'sqlind-minor-mode)))
-
(defun sql-indent-enable ()
"Enable `sqlind-minor-mode' if available and requested."
- (when (sql-is-indent-available)
+ (when (fboundp 'sqlind-minor-mode)
(sqlind-minor-mode (if sql-use-indent-support +1 -1))))
+;; Secure Password wallet
+
+(require 'auth-source)
+
+(defun sql-auth-source-search-wallet (wallet product user server database port)
+ "Read auth source WALLET to locate the USER secret.
+Sets `auth-sources' to WALLET and uses `auth-source-search' to locate the entry.
+The DATABASE and SERVER are concatenated with a slash between them as the
+host key."
+ (let* ((auth-sources wallet)
+ host
+ secret h-secret sd-secret)
+
+ ;; product
+ (setq product (symbol-name product))
+
+ ;; user
+ (setq user (unless (string-empty-p user) user))
+
+ ;; port
+ (setq port
+ (when (and port (numberp port) (not (zerop port)))
+ (number-to-string port)))
+
+ ;; server
+ (setq server (unless (string-empty-p server) server))
+
+ ;; database
+ (setq database (unless (string-empty-p database) database))
+
+ ;; host
+ (setq host (if server
+ (if database
+ (concat server "/" database)
+ server)
+ database))
+
+ ;; Perform search
+ (dolist (s (auth-source-search :max 1000))
+ (when (and
+ ;; Is PRODUCT specified, in the enty, and they are equal
+ (if product
+ (if (plist-member s :product)
+ (equal (plist-get s :product) product)
+ t)
+ t)
+ ;; Is USER specified, in the entry, and they are equal
+ (if user
+ (if (plist-member s :user)
+ (equal (plist-get s :user) user)
+ t)
+ t)
+ ;; Is PORT specified, in the entry, and they are equal
+ (if port
+ (if (plist-member s :port)
+ (equal (plist-get s :port) port)
+ t)
+ t))
+ ;; Is HOST specified, in the entry, and they are equal
+ ;; then the H-SECRET list
+ (if (and host
+ (plist-member s :host)
+ (equal (plist-get s :host) host))
+ (push s h-secret)
+ ;; Are SERVER and DATABASE specified, present, and equal
+ ;; then the SD-SECRET list
+ (if (and server
+ (plist-member s :server)
+ database
+ (plist-member s :database)
+ (equal (plist-get s :server) server)
+ (equal (plist-get s :database) database))
+ (push s sd-secret)
+ ;; Is SERVER specified, in the entry, and they are equal
+ ;; then the base SECRET list
+ (if (and server
+ (plist-member s :server)
+ (equal (plist-get s :server) server))
+ (push s secret)
+ ;; Is DATABASE specified, in the entry, and they are equal
+ ;; then the base SECRET list
+ (if (and database
+ (plist-member s :database)
+ (equal (plist-get s :database) database))
+ (push s secret)))))))
+ (setq secret (or h-secret sd-secret secret))
+
+ ;; If we found a single secret, return the password
+ (when (= 1 (length secret))
+ (setq secret (car secret))
+ (if (plist-member secret :secret)
+ (plist-get secret :secret)
+ nil))))
+
+(defcustom sql-password-wallet
+ (let (wallet w)
+ (dolist (ext '(".json.gpg" ".gpg" ".json" "") wallet)
+ (unless wallet
+ (setq w (locate-user-emacs-file (concat "sql-wallet" ext)
+ (concat ".sql-wallet" ext)))
+ (when (file-exists-p w)
+ (setq wallet w)))))
+ "Identification of the password wallet.
+See `sql-password-search-wallet-function' to understand how this value
+is used to locate the password wallet."
+ :type `(plist-get (symbol-plist 'auth-sources) 'custom-type)
+ :group 'SQL
+ :version "27.1")
+
+(defvar sql-password-search-wallet-function #'sql-auth-source-search-wallet
+ "Function to handle the lookup of the database password.
+The specified function will be called as:
+ (wallet-func WALLET PRODUCT USER SERVER DATABASE PORT)
+
+It is expected to return either a string containing the password,
+a function returning the password, or nil, If you want to support
+another format of password file, then implement a different
+search wallet function and identify the location of the password
+store with `sql-password-wallet'.")
+
;; misc customization of sql.el behavior
(defcustom sql-electric-stuff nil
@@ -804,7 +920,7 @@ Globally should be set to nil; it will be non-nil in `sql-mode',
(defvaralias 'sql-pop-to-buffer-after-send-region 'sql-display-sqli-buffer-function)
-(defcustom sql-display-sqli-buffer-function 'display-buffer
+(defcustom sql-display-sqli-buffer-function #'display-buffer
"Function to be called to display a SQLi buffer after `sql-send-*'.
When set to a function, it will be called to display the buffer.
@@ -2929,7 +3045,7 @@ displayed."
;;; Motion Functions
(defun sql-statement-regexp (prod)
- (let* ((ansi-stmt (sql-get-product-feature 'ansi :statement))
+ (let* ((ansi-stmt (or (sql-get-product-feature 'ansi :statement) "select"))
(prod-stmt (sql-get-product-feature prod :statement)))
(concat "^\\<"
(if prod-stmt
@@ -3199,6 +3315,10 @@ symbol `password', for the server if it contains the symbol
`database'. The members of WHAT are processed in the order in
which they are provided.
+If the `sql-password-wallet' is non-nil and WHAT contains the
+`password' token, then the `password' token will be pushed to the
+end to be sure that all of the values can be fed to the wallet.
+
Each token may also be a list with the token in the car and a
plist of options as the cdr. The following properties are
supported:
@@ -3210,6 +3330,15 @@ supported:
In order to ask the user for username, password and database, call the
function like this: (sql-get-login \\='user \\='password \\='database)."
+
+ ;; Push the password to the end if we have a wallet
+ (when (and sql-password-wallet
+ (fboundp sql-password-search-wallet-function)
+ (member 'password what))
+ (setq what (append (cl-delete 'password what)
+ '(password))))
+
+ ;; Prompt for each parameter
(dolist (w what)
(let ((plist (cdr-safe w)))
(pcase (or (car-safe w) w)
@@ -3218,7 +3347,19 @@ function like this: (sql-get-login \\='user \\='password \\='database)."
('password
(setq-default sql-password
- (read-passwd "Password: " nil (sql-default-value 'sql-password))))
+ (if (and sql-password-wallet
+ (fboundp sql-password-search-wallet-function))
+ (let ((password (funcall sql-password-search-wallet-function
+ sql-password-wallet
+ sql-product
+ sql-user
+ sql-server
+ sql-database
+ sql-port)))
+ (if password
+ password
+ (read-passwd "Password: " nil (sql-default-value 'sql-password))))
+ (read-passwd "Password: " nil (sql-default-value 'sql-password)))))
('server
(sql-get-login-ext 'sql-server "Server: " 'sql-server-history plist))
@@ -3535,8 +3676,8 @@ Allows the suppression of continuation prompts.")
;; Count how many newlines in the string
(setq sql-output-newline-count
- (apply #'+ (mapcar (lambda (ch)
- (if (eq ch ?\n) 1 0)) string)))
+ (apply #'+ (mapcar (lambda (ch) (if (eq ch ?\n) 1 0))
+ string)))
;; Send the string
(comint-simple-send proc string)))
@@ -4086,7 +4227,7 @@ must tell Emacs. Here's how to do that in your init file:
;; Set syntax and font-face highlighting
;; Catch changes to sql-product and highlight accordingly
(sql-set-product (or sql-product 'ansi)) ; Fixes bug#13591
- (add-hook 'hack-local-variables-hook 'sql-highlight-product t t))
+ (add-hook 'hack-local-variables-hook #'sql-highlight-product t t))
@@ -4094,7 +4235,7 @@ must tell Emacs. Here's how to do that in your init file:
(put 'sql-interactive-mode 'mode-class 'special)
(put 'sql-interactive-mode 'custom-mode-group 'SQL)
-
+;; FIXME: Why not use `define-derived-mode'?
(defun sql-interactive-mode ()
"Major mode to use a SQL interpreter interactively.
@@ -4156,13 +4297,15 @@ certain length.
\(add-hook \\='sql-interactive-mode-hook
(function (lambda ()
- (setq comint-output-filter-functions \\='comint-truncate-buffer))))
+ (setq comint-output-filter-functions #\\='comint-truncate-buffer))))
Here is another example. It will always put point back to the statement
you entered, right above the output it created.
\(setq comint-output-filter-functions
(function (lambda (STR) (comint-show-output))))"
+ ;; FIXME: The doc above uses `setq' on `comint-output-filter-functions',
+ ;; whereas hooks should be manipulated with things like `add/remove-hook'.
(delay-mode-hooks (comint-mode))
;; Get the `sql-product' for this interactive session.
@@ -4193,7 +4336,8 @@ you entered, right above the output it created.
(setq local-abbrev-table sql-mode-abbrev-table)
(setq abbrev-all-caps 1)
;; Exiting the process will call sql-stop.
- (set-process-sentinel (get-buffer-process (current-buffer)) 'sql-stop)
+ (let ((proc (get-buffer-process (current-buffer))))
+ (when proc (set-process-sentinel proc #'sql-stop)))
;; Save the connection and login params
(set (make-local-variable 'sql-user) sql-user)
(set (make-local-variable 'sql-database) sql-database)
@@ -4211,7 +4355,7 @@ you entered, right above the output it created.
(sql-make-alternate-buffer-name))
;; User stuff. Initialize before the hook.
(set (make-local-variable 'sql-prompt-regexp)
- (sql-get-product-feature sql-product :prompt-regexp))
+ (or (sql-get-product-feature sql-product :prompt-regexp) "^"))
(set (make-local-variable 'sql-prompt-length)
(sql-get-product-feature sql-product :prompt-length))
(set (make-local-variable 'sql-prompt-cont-regexp)
@@ -4219,7 +4363,7 @@ you entered, right above the output it created.
(make-local-variable 'sql-output-newline-count)
(make-local-variable 'sql-preoutput-hold)
(add-hook 'comint-preoutput-filter-functions
- 'sql-interactive-remove-continuation-prompt nil t)
+ #'sql-interactive-remove-continuation-prompt nil t)
(make-local-variable 'sql-input-ring-separator)
(make-local-variable 'sql-input-ring-file-name)
;; Run the mode hook (along with comint's hooks).
@@ -4230,7 +4374,7 @@ you entered, right above the output it created.
(concat "\\(" sql-prompt-regexp
"\\|" sql-prompt-cont-regexp "\\)")
sql-prompt-regexp))
- (setq left-margin sql-prompt-length)
+ (setq left-margin (or sql-prompt-length 0))
;; Install input sender
(set (make-local-variable 'comint-input-sender) 'sql-input-sender)
;; People wanting a different history file for each
@@ -4268,8 +4412,7 @@ Sentinels will always get the two parameters PROCESS and EVENT."
"Read a connection name."
(let ((completion-ignore-case t))
(completing-read prompt
- (mapcar (lambda (c) (car c))
- sql-connection-alist)
+ (mapcar #'car sql-connection-alist)
nil t initial 'sql-connection-history default)))
;;;###autoload
@@ -4480,6 +4623,10 @@ the call to \\[sql-product-interactive] with
(or sql-default-directory
default-directory)))
+ ;; The password wallet returns a function which supplies the password.
+ (when (functionp sql-password)
+ (setq sql-password (funcall sql-password)))
+
;; Call the COMINT service
(funcall (sql-get-product-feature product :sqli-comint-func)
product
@@ -4522,7 +4669,8 @@ the call to \\[sql-product-interactive] with
(let ((proc (get-buffer-process new-sqli-buffer))
(secs sql-login-delay)
(step 0.3))
- (while (and (memq (process-status proc) '(open run))
+ (while (and proc
+ (memq (process-status proc) '(open run))
(or (accept-process-output proc step)
(<= 0.0 (setq secs (- secs step))))
(progn (goto-char (point-max))
@@ -5226,8 +5374,7 @@ The default comes from `process-coding-system-alist' and
your might try undecided-dos as a coding system. If this doesn't help,
Try to set `comint-output-filter-functions' like this:
-\(setq comint-output-filter-functions (append comint-output-filter-functions
- \\='(comint-strip-ctrl-m)))
+\(add-hook 'comint-output-filter-functions #\\='comint-strip-ctrl-m 'append)
\(Type \\[describe-mode] in the SQL buffer for a list of commands.)"
(interactive "P")