From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Joost Kremers Newsgroups: gmane.emacs.help Subject: Re: first steps in elisp Date: Fri, 25 Nov 2016 09:00:47 +0100 Message-ID: <87zikoouog.fsf@fastmail.fm> References: <271a22de-593b-479d-a3d7-4aecbce934fb@googlegroups.com> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; format=flowed X-Trace: blaine.gmane.org 1480060905 5673 195.159.176.226 (25 Nov 2016 08:01:45 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Fri, 25 Nov 2016 08:01:45 +0000 (UTC) User-Agent: mu4e 0.9.17; emacs 25.1.50.3 Cc: help-gnu-emacs@gnu.org To: Mark Piffer Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Fri Nov 25 09:01:40 2016 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cABRw-00004u-9v for geh-help-gnu-emacs@m.gmane.org; Fri, 25 Nov 2016 09:01:36 +0100 Original-Received: from localhost ([::1]:44481 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cABS0-0005jt-05 for geh-help-gnu-emacs@m.gmane.org; Fri, 25 Nov 2016 03:01:40 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:37617) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cABRO-0005jj-1H for help-gnu-emacs@gnu.org; Fri, 25 Nov 2016 03:01:06 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cABRI-00039j-LE for help-gnu-emacs@gnu.org; Fri, 25 Nov 2016 03:01:02 -0500 Original-Received: from out5-smtp.messagingengine.com ([66.111.4.29]:58577) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cABRI-000391-Db for help-gnu-emacs@gnu.org; Fri, 25 Nov 2016 03:00:56 -0500 Original-Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id 740C4206E0; Fri, 25 Nov 2016 03:00:55 -0500 (EST) Original-Received: from frontend2 ([10.202.2.161]) by compute5.internal (MEProxy); Fri, 25 Nov 2016 03:00:55 -0500 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=fastmail.fm; h=cc :content-type:date:from:in-reply-to:message-id:mime-version :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc :x-sasl-enc; s=mesmtp; bh=wPV2oym6NfEZ2oBaBgGciK/480o=; b=QEuJ7O H99V1WxKMjJ066QuLHbf6f3CDD9OfiAtL4w7G4ZRIWAVOqn9p2surMANJrfH/yv3 KhI/9oaOe7TJ8xmwnvIfZ3u0gBpUUxFYhS26T05Jw/SeiC5/WpWGbzssn74lHr6t qoZMbihEhewXJgfTrdg+TdImh2DaMOjRC3Mlg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-sender :x-me-sender:x-sasl-enc:x-sasl-enc; s=smtpout; bh=wPV2oym6NfEZ2o BaBgGciK/480o=; b=TEfS/UnH8TgxlQbthM9AjeNn2R0pSJr7B3HriOFMNZ2Kct yV8K5lSsxcrHfhqGm0Zl4Juo/9aFe5enIeQvNu6tPLQEPnjQ+Cq4BBQFeQs57N+O iQ2EVN9KaNSQe6kH5TGhIaWIt59aYcu5S1CPqf8WNt1lxOaXglgVIEg4UZkD0= X-ME-Sender: X-Sasl-enc: MN1GqHyFzktMjYRwFJo0YYXckcEgmbLoU+2o2wl5qhbF 1480060854 Original-Received: from IdeaPad.messagingengine.com (x4d0aca9b.dyn.telefonica.de [77.10.202.155]) by mail.messagingengine.com (Postfix) with ESMTPA id 5FC2424E8E; Fri, 25 Nov 2016 03:00:54 -0500 (EST) In-reply-to: <271a22de-593b-479d-a3d7-4aecbce934fb@googlegroups.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.111.4.29 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "help-gnu-emacs" Xref: news.gmane.org gmane.emacs.help:111796 Archived-At: On Thu, Nov 24 2016, Mark Piffer wrote: > (defun ignore-multiline-comment (nlines) It's a good habit to get into to always provide a prefix for any Elisp functions and variables that you write, even if it's just for your own personal code. For personal code, most people use their initials, or simply `my-`. > "assumes point is inside a C multiline comment /*. Advances > until end of comment */ or nlines becomes 0" There are some doc string conventions (which can be found in the Elisp manual: C-h i m Elisp RET m Documentation Tips RET), the most important of which is that the first line of a doc string should be a sentence on its own. For personal code, it doesn't matter as much, of course, but again, it's a good habit to get into. Also, the doc string should say what a function does, i.e., what it expects as input (or context) and what it returns or what side effects it has. So, e.g.,: "Move point past the end of a C multiline comment. This function assumes that point is inside the comment. This is a recursive function, its stop condition is met when NLINES is 0." > (if (zerop nlines) > nil > (if (looking-at ".*?\\*/") > (progn > (goto-char (match-end 0)) > (ignore-line-comments nlines)) > (beginning-of-line 2) > (ignore-multiline-comment (1- nlines))))) Personally, I normally wouldn't explicitly write nil as a return value but instead rely on the function structure to handle that. So I'd do something like: ``` (defun my-ignore-multiline-comment (nlines) "assumes point is inside a C multiline comment /*. Advances until end of comment */ or nlines becomes 0" (when (not (zerop nlines)) (if (looking-at ".*?\\*/") (progn (goto-char (match-end 0)) (my-ignore-line-comments nlines)) (beginning-of-line 2) (my-ignore-multiline-comment (1- nlines))))) ``` But in this case the nil return value might make sense to indicate that the stop condition is met. Personally, I would probably write that in the doc string, but YMMV. > (defun ignore-line-comments (nlines) > "return the text starting at point as a list, going nlines > lines down, stripped of > all C comments (except pathological cases w/ string literals)" > (if (zerop nlines) > nil > (setq ml-e (if (looking-at "\\(.*?\\)/\\*") ;; test on /* > comment > (match-end 1) > nil)) > (setq sl-e (if (looking-at "\\(.*?\\)//") ;; test on // > comment > (match-end 1) > nil)) Here, you should definitely use local variables for ml-e and sl-e. Note that if you use setq on a symbol that hasn't been let-bound, you automatically create a global variable that stays around until Emacs is shut down. So unless you need to store some global state, always use let. Also, I would use longer names for variables, so it's easier to see what they're used for. But again, YMMV. > (if (or sl-e ml-e) ;; any comment on line? > (if (and ml-e (or (not sl-e) (< ml-e sl-e))) ;; > is /* the only or first comment? > (progn > (setq r (buffer-substring-no-properties > (point) ml-e)) > (goto-char ml-e) > (cons r (ignore-multiline-comment > nlines))) > (setq r (buffer-substring-no-properties (point) > sl-e)) > (beginning-of-line 2) > (cons r (ignore-line-comments (1- nlines)))) > (looking-at ".*$") > (setq r (buffer-substring-no-properties (car (match-data)) > (cadr (match-data))) ) > (beginning-of-line 2) > (cons r (ignore-line-comments (1- nlines)))))) So with let, this would become: ``` (defun my-ignore-line-comments (nlines) "return the text starting at point as a list, going nlines lines down, stripped of all C comments (except pathological cases w/ string literals)" (when (not (zerop nlines)) (let ((ml-e (if (looking-at "\\(.*?\\)/\\*") ;; test on /* comment (match-end 1) nil)) (sl-e (if (looking-at "\\(.*?\\)//") ;; test on // comment (match-end 1) nil)) r) (if (or sl-e ml-e) ;; any comment on line? (if (and ml-e (or (not sl-e) (< ml-e sl-e))) ;; is /* the only or first comment? (progn (setq r (buffer-substring-no-properties (point) ml-e)) (goto-char ml-e) (cons r (my-ignore-multiline-comment nlines))) (setq r (buffer-substring-no-properties (point) sl-e)) (beginning-of-line 2) (cons r (my-ignore-line-comments (1- nlines)))) (looking-at ".*$") (setq r (buffer-substring-no-properties (car (match-data)) (cadr (match-data)))) (beginning-of-line 2) (cons r (my-ignore-line-comments (1- nlines))))))) ``` It's perfectly fine to use setq on a variable once it's been let-bound. If you cannot provide an initial value for a variable, just leave out the value as done here for `r` and setq it later. BTW, I find it useful to run flycheck in my Elisp buffers, helps one to develop good habits. :-) HTH -- Joost Kremers Life has its moments