From mboxrd@z Thu Jan  1 00:00:00 1970
Path: news.gmane.org!not-for-mail
From: mail@ap4y.me
Newsgroups: gmane.emacs.bugs
Subject: bug#21896: 24.5; Inconsistent handling of braces in smie
Date: Fri, 13 Nov 2015 16:09:39 +1300
Message-ID: <87bnayzjbg.fsf@home.i-did-not-set--mail-host-address--so-tickle-me>
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
X-Trace: ger.gmane.org 1447384463 32298 80.91.229.3 (13 Nov 2015 03:14:23 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Fri, 13 Nov 2015 03:14:23 +0000 (UTC)
To: 21896@debbugs.gnu.org
Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Fri Nov 13 04:14:12 2015
Return-path: <bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org>
Envelope-to: geb-bug-gnu-emacs@m.gmane.org
Original-Received: from lists.gnu.org ([208.118.235.17])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org>)
	id 1Zx4oV-00016m-2w
	for geb-bug-gnu-emacs@m.gmane.org; Fri, 13 Nov 2015 04:14:11 +0100
Original-Received: from localhost ([::1]:50788 helo=lists.gnu.org)
	by lists.gnu.org with esmtp (Exim 4.71)
	(envelope-from <bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org>)
	id 1Zx4oU-0003Eo-LI
	for geb-bug-gnu-emacs@m.gmane.org; Thu, 12 Nov 2015 22:14:10 -0500
Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:37038)
	by lists.gnu.org with esmtp (Exim 4.71)
	(envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1Zx4oQ-0003De-7Q
	for bug-gnu-emacs@gnu.org; Thu, 12 Nov 2015 22:14:07 -0500
Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)
	(envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1Zx4oM-0007eI-UL
	for bug-gnu-emacs@gnu.org; Thu, 12 Nov 2015 22:14:06 -0500
Original-Received: from debbugs.gnu.org ([208.118.235.43]:46755)
	by eggs.gnu.org with esmtp (Exim 4.71)
	(envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1Zx4oM-0007eE-R1
	for bug-gnu-emacs@gnu.org; Thu, 12 Nov 2015 22:14:02 -0500
Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.80)
	(envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1Zx4oM-0001Z3-9k
	for bug-gnu-emacs@gnu.org; Thu, 12 Nov 2015 22:14:02 -0500
X-Loop: help-debbugs@gnu.org
Resent-From: mail@ap4y.me
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces@debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@gnu.org
Resent-Date: Fri, 13 Nov 2015 03:14:01 +0000
Resent-Message-ID: <handler.21896.B.14473843825928@debbugs.gnu.org>
Resent-Sender: help-debbugs@gnu.org
X-GNU-PR-Message: report 21896
X-GNU-PR-Package: emacs
X-GNU-PR-Keywords: 
X-Debbugs-Original-To: bug-gnu-emacs@gnu.org
Original-Received: via spool by submit@debbugs.gnu.org id=B.14473843825928
	(code B ref -1); Fri, 13 Nov 2015 03:14:01 +0000
Original-Received: (at submit) by debbugs.gnu.org; 13 Nov 2015 03:13:02 +0000
Original-Received: from localhost ([127.0.0.1]:36463 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.80)
	(envelope-from <debbugs-submit-bounces@debbugs.gnu.org>)
	id 1Zx4n6-0001Wx-0g
	for submit@debbugs.gnu.org; Thu, 12 Nov 2015 22:13:02 -0500
Original-Received: from eggs.gnu.org ([208.118.235.92]:54473)
	by debbugs.gnu.org with esmtp (Exim 4.80)
	(envelope-from <mail@ap4y.me>) id 1Zx4kS-0001Se-Rn
	for submit@debbugs.gnu.org; Thu, 12 Nov 2015 22:10:02 -0500
Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)
	(envelope-from <mail@ap4y.me>) id 1Zx4kR-0006gx-I8
	for submit@debbugs.gnu.org; Thu, 12 Nov 2015 22:10:00 -0500
Original-Received: from lists.gnu.org ([2001:4830:134:3::11]:60008)
	by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from <mail@ap4y.me>)
	id 1Zx4kR-0006gs-EK
	for submit@debbugs.gnu.org; Thu, 12 Nov 2015 22:09:59 -0500
Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:36245)
	by lists.gnu.org with esmtp (Exim 4.71)
	(envelope-from <mail@ap4y.me>) id 1Zx4kP-0005cr-VE
	for bug-gnu-emacs@gnu.org; Thu, 12 Nov 2015 22:09:59 -0500
Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)
	(envelope-from <mail@ap4y.me>) id 1Zx4kM-0006ga-Mh
	for bug-gnu-emacs@gnu.org; Thu, 12 Nov 2015 22:09:57 -0500
Original-Received: from ap4y.me ([45.79.156.233]:60151)
	by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from <mail@ap4y.me>)
	id 1Zx4kM-0006gV-HJ
	for bug-gnu-emacs@gnu.org; Thu, 12 Nov 2015 22:09:54 -0500
Original-Received: from [127.0.0.1] (localhost [127.0.0.1])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by ap4y.me (Postfix) with ESMTPSA id 0DCC858E
	for <bug-gnu-emacs@gnu.org>; Fri, 13 Nov 2015 03:09:43 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ap4y.me; s=default;
	t=1447384184; bh=fKQly7e6k8JecbF/uK+cJIaLl/3XwSpQNGZnp4YRzlc=;
	h=From:To:Subject:Date:From;
	b=c7xyPZDZ+7Ka3VCXT7d7V8dGOI/EO79SSQFNURjJdYbUDWDNopJax1h/BIVgnEwUk
	cYRH18YXaVlJBzFz5Iw8X6l9xypSYiTcdCz4MZ7Rt8DbuKfrHh2KUn3gG5V9AIs2W/
	drY4R9mMfdFWANHAY+4En7ya/G0fmDmp9ljzqtwA=
X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic]
X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address
	(bad octet value).
X-Mailman-Approved-At: Thu, 12 Nov 2015 22:12:41 -0500
X-BeenThere: debbugs-submit@debbugs.gnu.org
X-Mailman-Version: 2.1.15
Precedence: list
X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x
X-Received-From: 208.118.235.43
X-BeenThere: bug-gnu-emacs@gnu.org
List-Id: "Bug reports for GNU Emacs,
	the Swiss army knife of text editors" <bug-gnu-emacs.gnu.org>
List-Unsubscribe: <https://lists.gnu.org/mailman/options/bug-gnu-emacs>,
	<mailto:bug-gnu-emacs-request@gnu.org?subject=unsubscribe>
List-Archive: <http://lists.gnu.org/archive/html/bug-gnu-emacs>
List-Post: <mailto:bug-gnu-emacs@gnu.org>
List-Help: <mailto:bug-gnu-emacs-request@gnu.org?subject=help>
List-Subscribe: <https://lists.gnu.org/mailman/listinfo/bug-gnu-emacs>,
	<mailto:bug-gnu-emacs-request@gnu.org?subject=subscribe>
Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org
Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org
Xref: news.gmane.org gmane.emacs.bugs:108703
Archived-At: <http://permalink.gmane.org/gmane.emacs.bugs/108703>

--=-=-=
Content-Type: text/plain


For a smie grammar like this:

(id)
(inst ("if" exp "{" insts "}")
      (exp))
(insts (insts ";" insts) (inst))
(exp (exp "." id)
     (id ":" exp)
     (exp "=" exp))
(exps (exps "," exps) (exp))

Using 2 possible ways of hanling braces tokens:

1. Using default lexer rules for braces (as per documentation).
2. Manually tokenizing braces in lexer (uncomment lines 196-197 and
213-214 in provided source file)

I'm getting different indentation results. For the case number 1,
indentation of the consutriction:

if true {
    |foo
}

is invalid and from the logs it seems like smie doesn't parse this
constructor correctly.

For the case number 2 indentation works as expected, but for the
construction like this (which is a simple sexp):

{
}|

I'm getting "Mismatching parenthesis" error when I'm calling
blink-matching-open.


--=-=-=
Content-Type: application/emacs-lisp
Content-Disposition: attachment; filename=swift-mode.el
Content-Transfer-Encoding: quoted-printable

;;; swift-mode.el --- Major-mode for Apple's Swift programming language. -*=
- lexical-binding: t -*-

;; Copyright (C) 2014 Chris Barrett, Bozhidar Batsov, Arthur Evstifeev

;; Authors: Chris Barrett <chris.d.barrett@me.com>
;;       Bozhidar Batsov <bozhidar@batsov.com>
;;       Arthur Evstifeev <lod@pisem.net>
;; Version: 0.4.0-cvs
;; Package-Requires: ((emacs "24.4"))
;; Keywords: languages swift

;; This file is not part of GNU Emacs.

;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; Major-mode for Apple's Swift programming language.

;;; Code:

(require 'rx)
(require 'comint)
(require 'cl-lib)

(defgroup swift nil
  "Configuration for swift-mode."
  :group 'languages
  :prefix "swift-")

(defcustom swift-indent-offset 4
  "Defines the indentation offset for Swift code."
  :group 'swift
  :type 'integer)

(defcustom swift-indent-switch-case-offset 0
  "Defines the indentation offset for cases in a switch statement."
  :group 'swift
  :type 'integer)

(defcustom swift-indent-multiline-statement-offset 2
  "Defines the indentation offset for multiline statements."
  :group 'swift
  :type 'integer
  :package-version '(swift-mode "0.3.0"))

(defcustom swift-indent-hanging-comma-offset nil
  "Defines the indentation offset for hanging comma."
  :group 'swift
  :type '(choice (const :tag "Use default relative formatting" nil)
                 (integer :tag "Custom offset"))
  :package-version '(swift-mode "0.4.0"))

(defcustom swift-repl-executable
  "xcrun swift"
  "Path to the Swift CLI."
  :group 'swift)

;;; Indentation

(require 'smie)

(defconst swift-smie-grammar
  (smie-prec2->grammar
   (smie-merge-prec2s
    (smie-bnf->prec2
     '((id)
       (inst ("if" exp "{" insts "}")
             (exp))
       (insts (insts ";" insts) (inst))
       (exp (exp "." id)
            (id ":" exp)
            (exp "=3D" exp))
       (exps (exps "," exps) (exp)))
     ;; Conflicts
     '((assoc ";"))
     '((assoc ","))
     '((right "=3D") (assoc ".") (assoc ":") (assoc ",")))

    (smie-precs->prec2
     '(
       (right "*=3D" "/=3D" "%=3D" "+=3D" "-=3D" "<<=3D" ">>=3D" "&=3D"
              "^=3D" "|=3D" "&&=3D" "||=3D" "=3D")                       ;;=
 Assignment (Right associative, precedence level 90)
       (right "?" ":")                                         ;; Ternary C=
onditional (Right associative, precedence level 100)
       (left "||")                                             ;; Disjuncti=
ve (Left associative, precedence level 110)
       (left "&&")                                             ;; Conjuncti=
ve (Left associative, precedence level 120)
       (right "??")                                            ;; Nil Coale=
scing (Right associativity, precedence level 120)
       (nonassoc "<" "<=3D" ">" ">=3D" "=3D=3D" "!=3D" "=3D=3D=3D" "!=3D=3D=
" "~=3D") ;; Comparative (No associativity, precedence level 130)
       (nonassoc "is" "as" "as!" "as?")                        ;; Cast (No =
associativity, precedence level 132)
       (nonassoc "..<" "...")                                  ;; Range (No=
 associativity, precedence level 135)
       (left "+" "-" "&+" "&-" "|" "^")                        ;; Additive =
(Left associative, precedence level 140)
       (left "*" "/" "%" "&*" "&/" "&%" "&")                   ;; Multiplic=
ative (Left associative, precedence level 150)
       (nonassoc "<<" ">>")                                    ;; Exponenti=
ative (No associativity, precedence level 160)
       ))
    )))

(defun verbose-swift-smie-rules (kind token)
  (let ((value (swift-smie-rules kind token)))
    (message "%s '%s'; sibling-p:%s parent:%s hanging:%s =3D=3D %s" kind to=
ken
             (ignore-errors (smie-rule-sibling-p))
             (ignore-errors smie--parent)
             (ignore-errors (smie-rule-hanging-p))
             value)
    value))

(defvar swift-smie--operators
  '("*=3D" "/=3D" "%=3D" "+=3D" "-=3D" "<<=3D" ">>=3D" "&=3D" "^=3D" "|=3D"=
 "&&=3D" "||=3D"
   "<" "<=3D" ">" ">=3D" "=3D=3D" "!=3D" "=3D=3D=3D" "!=3D=3D" "~=3D" "||" =
"&&"
   "is" "as" "as!" "as?" "..<" "..."
   "+" "-" "&+" "&-" "|" "^"
   "*" "/" "%" "&*" "&/" "&%" "&"
   "<<" ">>" "??"))

(defvar swift-smie--operators-regexp
  (regexp-opt swift-smie--operators))

(defun swift-smie--implicit-semi-p ()
  (save-excursion
    (skip-chars-backward " \t")
    (not (or (bolp)
             (memq (char-before) '(?\{ ?\[ ?, ?. ?: ?=3D ?\())
             ;; Checking for operators form for "?" and "!",
             ;; they can be a part of the type.
             ;; Special case: is? and as? are operators.
             (looking-back "[[:space:]][?!]" (- (point) 2) t)
             ;; ??, is? and as? are operators
             (looking-back "[?][?]\\|as[?]\\|is[?]" (- (point) 3) t)
             ;; "in" operator in closure
             (looking-back "\\bin" (- (point) 3) t)
             ;; Characters placed on the second line in multi-line expressi=
on
             (save-excursion
               (forward-comment (buffer-size))
               (looking-at "[.?:()]"))
             ;; Operators placed on the second line in multi-line expression
             ;; Should respect here possible comments strict before the lin=
ebreak
             (save-excursion
               (forward-comment (buffer-size))
               (looking-at swift-smie--operators-regexp))

             (and (looking-back swift-smie--operators-regexp (- (point) 3) =
t)
                  ;; Not a generic type
                  (not (looking-back "[[:upper:]]>" (- (point) 2) t)))
             ))))

(defun swift-smie--forward-token-debug ()
  (let ((op (point))
        (token (swift-smie--forward-token)))
    (message "forward: %s -> %s =3D %s" op (point) token)
    token
    ))

(defun swift-smie--backward-token-debug ()
  (let ((op (point))
        (token (swift-smie--backward-token)))
    (message "backward: %s -> %s =3D %s" op (point) token)
      token
    ))

(defvar swift-smie--case-exp-regexp
  "\\(case.*?[^{}:=3D]+\\|default[[:space:]]*\\):")

(defun swift-smie--case-signature-p ()
  (save-excursion
    (up-list 1) (backward-list 1)
    (not (looking-back "enum.*" (line-beginning-position -1)))))

(defun swift-smie--closure-signature-p ()
    (let ((tok (smie-default-forward-token)))
      (or (equal tok "in")
          (and (equal tok "->")
               (equal (smie-default-forward-token) "in")))))

(defun swift-smie--forward-token ()
  (skip-chars-forward " \t")
  (cond
   ((and (looking-at "\n\\|\/\/")
         (swift-smie--implicit-semi-p))
    (if (eolp) (forward-char 1) (forward-comment 1))
    (skip-chars-forward " \t")
    (if (looking-at swift-smie--case-exp-regexp)
        "case-;" ";"))
   (t
    (forward-comment (point-max))
    (cond
     ;; ((looking-at "{") (forward-char 1) "{")
     ;; ((looking-at "}") (forward-char 1) "}")

     (t (smie-default-forward-token))
     ))))

(defun swift-smie--backward-token ()
  (let ((pos (point)))
    (forward-comment (- (point)))
    (cond
     ((and (> pos (line-end-position))
           (swift-smie--implicit-semi-p))
      (if (save-excursion
            (forward-comment 1)
            (looking-at swift-smie--case-exp-regexp))
          "case-;" ";"))

     ;; ((eq (char-before) ?\{) (backward-char 1) "{")
     ;; ((eq (char-before) ?\}) (backward-char 1) "}")

     (t (smie-default-backward-token))
     )))

(defun swift-smie-rules (kind token)
  (pcase (cons kind token)
    (`(:elem . basic) swift-indent-offset)))

;;; Font lock

(defvar swift-mode--type-decl-keywords
  '("class" "enum" "protocol" "struct" "typealias"))

(defvar swift-mode--val-decl-keywords
  '("let" "var"))

(defvar swift-mode--context-variables-keywords
  '("self" "super"))

(defvar swift-mode--fn-decl-keywords
  '("deinit" "func" "init"))

(defvar swift-mode--misc-keywords
  '("import" "static" "subscript" "extension"))

(defvar swift-mode--statement-keywords
  '("break" "case" "continue" "default" "do" "else" "fallthrough"
    "if" "in" "for" "return" "switch" "where" "repeat" "while" "guard"))

(defvar swift-mode--contextual-keywords
  '("associativity" "didSet" "get" "infix" "inout" "left" "mutating" "none"
    "nonmutating" "operator" "override" "postfix" "precedence" "prefix" "ri=
ght"
    "set" "unowned" "unowned(safe)" "unowned(unsafe)" "weak" "willSet" "con=
venience"
    "required" "dynamic" "final" "lazy" "optional" "private" "public" "inte=
rnal"))

(defvar swift-mode--attribute-keywords
  '("class_protocol" "exported" "noreturn"
    "NSCopying" "NSManaged" "objc" "autoclosure"
    "available" "noescape" "nonobjc" "NSApplicationMain" "testable" "UIAppl=
icationMain" "warn_unused_result" "convention"
    "IBAction" "IBDesignable" "IBInspectable" "IBOutlet"))

(defvar swift-mode--keywords
  (append swift-mode--type-decl-keywords
          swift-mode--val-decl-keywords
          swift-mode--context-variables-keywords
          swift-mode--fn-decl-keywords
          swift-mode--misc-keywords
          swift-mode--statement-keywords
          swift-mode--contextual-keywords)
  "Keywords used in the Swift language.")

(defvar swift-mode--constants
  '("true" "false" "nil"))

(defvar swift-font-lock-keywords
  `(
    ;; Keywords
    ;;
    ;; Swift allows reserved words to be used as identifiers when enclosed
    ;; with backticks, in which case they should be highlighted as
    ;; identifiers, not keywords.
    (,(rx-to-string
       `(and (or bol (not (any "`"))) bow
             (group (or ,@swift-mode--keywords))
             eow)
       t)
     1 font-lock-keyword-face)

    ;; Attributes
    ;;
    ;; Highlight attributes with keyword face
    (,(rx-to-string
       `(and "@" bow (or ,@swift-mode--attribute-keywords) eow)
       t)
     0 font-lock-keyword-face)

    ;; Types
    ;;
    ;; Any token beginning with an uppercase character is highlighted as a
    ;; type.
    (,(rx bow upper (* word) eow)
     0 font-lock-type-face)

    ;; Function names
    ;;
    ;; Any token beginning after `func' is highlighted as a function name.
    (,(rx bow "func" eow (+ space) (group bow (+ word) eow))
     1 font-lock-function-name-face)

    ;; Value bindings
    ;;
    ;; Any token beginning after `let' or `var' is highlighted as an
    ;; identifier.
    (,(rx-to-string `(and bow
                           (or ,@swift-mode--val-decl-keywords)
                           eow
                           (+ space)
                           (? "(")
                           (group (+ (or (+ (? ?`) word (? ?`)) ?, space)))
                           (? ")"))
                     t)
       1 font-lock-variable-name-face)

    ;; Use high-visibility face for pattern match wildcards.
    (,(rx (not (any word digit)) (group "_") (or eol (not (any word digit))=
))
     1 font-lock-negation-char-face)

    ;; Constants
    ;;
    ;; Highlight nil and boolean literals.
    (,(rx-to-string `(and bow (or ,@swift-mode--constants) eow))
     0 font-lock-constant-face)

    ;; Attributes
    ;;
    ;; Use string face for attribute name.
    (,(rx (or bol space)(group "@" (+ word)) eow)
     1 font-lock-string-face)

    ;; Imported modules
    ;;
    ;; Highlight the names of imported modules. Use `font-lock-string-face'=
 for
    ;; consistency with C modes.
    (,(rx bow "import" eow (+ space) (group (+ word)))
     1 font-lock-string-face)

    ;; String interpolation
    ;;
    ;; Highlight interpolation expression as identifier.
    (swift-match-interpolation 0 font-lock-variable-name-face t)
    ))

(defun swift-syntax-propertize-function (start end)
  "Syntactic keywords for Swift mode."
  (let (case-fold-search)
    (goto-char start)
    (remove-text-properties start end '(swift-interpolation-match-data))
    (funcall
     (syntax-propertize-rules
      ((rx (group "\\(" (* (any alnum " ()+-._/*[]!?<>&~!:|^%")) ")"))
       (0 (ignore (swift-syntax-propertize-interpolation)))))
     start end)))

(defun swift-syntax-propertize-interpolation ()
  (let* ((beg (match-beginning 0))
         (context (save-excursion (save-match-data (syntax-ppss beg)))))
    (put-text-property beg (1+ beg) 'swift-interpolation-match-data
                       (cons (nth 3 context) (match-data)))))

(defun swift-match-interpolation (limit)
  (let ((pos (next-single-char-property-change (point) 'swift-interpolation=
-match-data
                                               nil limit)))
    (when (and pos (> pos (point)))
      (goto-char pos)
      (let ((value (get-text-property pos 'swift-interpolation-match-data)))
        (if (eq (car value) ?\")
            (progn
              (set-match-data (cdr value))
              t)
          (swift-match-interpolation limit))))))

;;; Imenu

(defun swift-mode--mk-regex-for-def (keyword)
  "Make a regex matching the identifier introduced by KEYWORD."
  (let ((ident (rx (any word nonascii "_") (* (any word nonascii digit "_")=
))))
    (rx-to-string `(and bow ,keyword eow (+ space) (group (regexp ,ident)))
                  t)))

(defvar swift-mode--imenu-generic-expression
  (list
   (list "Functions" (swift-mode--mk-regex-for-def "func") 1)
   (list "Classes"   (swift-mode--mk-regex-for-def "class") 1)
   (list "Enums"     (swift-mode--mk-regex-for-def "enum") 1)
   (list "Protocols" (swift-mode--mk-regex-for-def "protocol") 1)
   (list "Structs"   (swift-mode--mk-regex-for-def "struct") 1)
   (list "Constants" (swift-mode--mk-regex-for-def "let") 1)
   (list "Variables" (swift-mode--mk-regex-for-def "var") 1))
  "Value for `imenu-generic-expression' in swift-mode.")

;;; Flycheck

(with-eval-after-load 'flycheck
  (flycheck-def-option-var flycheck-swift-sdk-path nil swift
     "A path to the targeted SDK"
     :type '(choice (const :tag "Don't link against sdk" nil)
                    (string :tag "Targeted SDK path"))
     :safe #'stringp)

   (flycheck-def-option-var flycheck-swift-linked-sources nil swift
     "Source files path to link against. Can be glob, i.e. *.swift"
     :type '(choice (const :tag "Don't use linked sources" nil)
                    (string :tag "Linked Sources"))
     :safe #'stringp)

   (flycheck-def-option-var flycheck-swift-framework-search-paths nil swift
     "A list of framework search paths"
     :type '(repeat (directory :tag "Include directory"))
     :safe #'flycheck-string-list-p)

   (flycheck-def-option-var flycheck-swift-cc-include-search-paths nil swift
     "A list of include file search paths to pass to the Objective C compil=
er"
     :type '(repeat (directory :tag "Include directory"))
     :safe #'flycheck-string-list-p)

   (flycheck-def-option-var flycheck-swift-target "i386-apple-ios8.1" swift
     "Target used by swift compiler"
     :type '(choice (const :tag "Don't specify target" nil)
                    (string :tag "Build target"))
     :safe #'stringp)

   (flycheck-def-option-var flycheck-swift-import-objc-header nil swift
     "Objective C header file to import, if any"
     :type '(choice (const :tag "Don't specify objective C bridging header"=
 nil)
                    (string :tag "Objective C bridging header path"))
     :safe #'stringp)

   (flycheck-define-checker swift
     "Flycheck plugin for for Apple's Swift programming language."
     :command ("swift"
               "-frontend" "-parse"
               (option "-sdk" flycheck-swift-sdk-path)
               (option-list "-F" flycheck-swift-framework-search-paths)
               ;; Swift compiler will complain about redeclaration
               ;; if we will include original file along with
               ;; temporary source file created by flycheck.
               ;; We also don't want a hidden emacs interlock files.
               (eval
                (let (source file)
                  (when flycheck-swift-linked-sources
                    (setq source (car (flycheck-substitute-argument 'source=
 'swift)))
                    (setq file (file-name-nondirectory source))
                    (cl-remove-if-not
                     #'(lambda (path)
                         (and
                          (eq (string-match ".#" path) nil)
                          (eq (string-match file path) nil)))
                     (file-expand-wildcards flycheck-swift-linked-sources))=
)))
               (option "-target" flycheck-swift-target)
               (option "-import-objc-header" flycheck-swift-import-objc-hea=
der)
               (eval
                (cl-mapcan
                 #'(lambda (path) (list "-Xcc" (concat "-I" path)))
                 flycheck-swift-cc-include-search-paths))
               "-primary-file" source)
     :error-patterns
     ((error line-start (file-name) ":" line ":" column ": "
             "error: " (message) line-end)
      (warning line-start (file-name) ":" line ":" column ": "
               "warning: " (message) line-end))
     :modes swift-mode))

;;; REPL

(defvar swift-repl-buffer nil
  "Stores the name of the current swift REPL buffer, or nil.")

;;;###autoload
(defun swift-mode-run-repl (cmd &optional dont-switch-p)
  "Run a REPL process, input and output via buffer `*swift-repl*'.
If there is a process already running in `*swift-repl*', switch to that buf=
fer.
With argument CMD allows you to edit the command line (default is value
of `swift-repl-executable').
With DONT-SWITCH-P cursor will stay in current buffer.
Runs the hook `swift-repl-mode-hook' \(after the `comint-mode-hook'
is run).
\(Type \\[describe-mode] in the process buffer for a list of commands.)"

  (interactive (list (if current-prefix-arg
                         (read-string "Run swift REPL: " swift-repl-executa=
ble)
                       swift-repl-executable)))
  (unless (comint-check-proc "*swift-repl*")
    (save-excursion (let ((cmdlist (split-string cmd)))
                      (set-buffer (apply 'make-comint "swift-repl" (car cmd=
list)
                                         nil (cdr cmdlist)))
                      (swift-repl-mode))))
  (setq swift-repl-executable cmd)
  (setq swift-repl-buffer "*swift-repl*")
  (unless dont-switch-p
    (pop-to-buffer "*swift-repl*")))

(defun swift-mode-send-region (start end)
  "Send the current region to the inferior swift process.
START and END define region within current buffer"
  (interactive "r")
  (swift-mode-run-repl swift-repl-executable t)
  (comint-send-region swift-repl-buffer start end)
  (comint-send-string swift-repl-buffer "\n"))

(defun swift-mode-send-buffer ()
  "Send the buffer to the Swift REPL process."
  (interactive)
  (swift-mode-send-region (point-min) (point-max)))

(define-derived-mode swift-repl-mode comint-mode "Swift REPL"
  "Major mode for interacting with Swift REPL.

A REPL can be fired up with M-x swift-mode-run-repl.

Customization: Entry to this mode runs the hooks on comint-mode-hook and
swift-repl-mode-hook (in that order).

You can send text to the REPL process from other buffers containing source.
    swift-mode-send-region sends the current region to the REPL process,
    swift-mode-send-buffer sends the current buffer to the REPL process.
")

;;; Mode definition

(defvar swift-mode-syntax-table
  (let ((table (make-syntax-table)))

    ;; Operators
    (dolist (i '(?+ ?- ?* ?/ ?& ?| ?^ ?< ?> ?~))
      (modify-syntax-entry i "." table))

    ;; Strings
    (modify-syntax-entry ?\" "\"" table)
    (modify-syntax-entry ?\\ "\\" table)

    ;; Additional symbols
    (modify-syntax-entry ?_ "w" table)
    (modify-syntax-entry ?? "_" table)
    (modify-syntax-entry ?! "_" table)
    (modify-syntax-entry ?: "." table)

    ;; Comments
    (modify-syntax-entry ?/  ". 124b" table)
    (modify-syntax-entry ?*  ". 23n"  table)
    (modify-syntax-entry ?\n "> b"    table)

    ;; Parenthesis, braces and brackets
    (modify-syntax-entry ?\( "()" table)
    (modify-syntax-entry ?\) ")(" table)
    (modify-syntax-entry ?\[ "(]" table)
    (modify-syntax-entry ?\] ")[" table)
    (modify-syntax-entry ?\{ "(}" table)
    (modify-syntax-entry ?\} "){" table)

    table))

(defvar swift-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "C-c C-z") 'swift-mode-run-repl)
    (define-key map (kbd "C-c C-f") 'swift-mode-send-buffer)
    (define-key map (kbd "C-c C-r") 'swift-mode-send-region)
    (easy-menu-define swift-menu map "Swift Mode menu"
      `("Swift"
        :help "Swift-specific Features"
        ["Run REPL" swift-mode-run-repl
         :help "Run Swift REPL"]
        ["Send buffer to REPL" swift-mode-send-buffer
         :help "Send the current buffer's contents to the REPL"]
        ["Send region to REPL" swift-mode-send-region
         :help "Send currently selected region to the REPL"]))
    map)
  "Key map for swift mode.")

;;;###autoload
(define-derived-mode swift-mode prog-mode "Swift"
  "Major mode for Apple's Swift programming language.

\\<swift-mode-map>"
  :group 'swift
  :syntax-table swift-mode-syntax-table
  (setq font-lock-defaults '((swift-font-lock-keywords) nil nil))
  (setq-local syntax-propertize-function #'swift-syntax-propertize-function)

  (setq-local imenu-generic-expression swift-mode--imenu-generic-expression)

  (setq-local comment-start "// ")
  (setq-local comment-end "")
  (setq-local indent-tabs-mode nil)
  (setq-local electric-indent-chars
              (append '(?. ?, ?: ?\) ?\] ?\}) electric-indent-chars))
  (smie-setup swift-smie-grammar 'verbose-swift-smie-rules ;; 'verbose-swif=
t-smie-rules
              :forward-token 'swift-smie--forward-token-debug
              :backward-token 'swift-smie--backward-token-debug))

;;;###autoload
(add-to-list 'auto-mode-alist '("\\.swift\\'" . swift-mode))

(provide 'swift-mode)

;;; swift-mode.el ends here

--=-=-=
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable





In GNU Emacs 24.5.1 (x86_64-unknown-linux-gnu, GTK+ Version 3.16.6)
 of 2015-09-10 on foutrelis
Windowing system distributor `The X.Org Foundation', version 11.0.11704000
System Description:	Arch Linux

Configured using:
 `configure --prefix=3D/usr --sysconfdir=3D/etc --libexecdir=3D/usr/lib
 --localstatedir=3D/var --with-x-toolkit=3Dgtk3 --with-xft
 'CFLAGS=3D-march=3Dx86-64 -mtune=3Dgeneric -O2 -pipe -fstack-protector-str=
ong
 --param=3Dssp-buffer-size=3D4' CPPFLAGS=3D-D_FORTIFY_SOURCE=3D2
 LDFLAGS=3D-Wl,-O1,--sort-common,--as-needed,-z,relro'

Important settings:
  value of $EMACSLOADPATH: /home/ap4y/github/swift-mode/.cask/24.5.1/elpa/f=
lycheck-cask-20150920.453:/home/ap4y/github/swift-mode/.cask/24.5.1/elpa/fl=
ycheck-20151027.755:/home/ap4y/github/swift-mode/.cask/24.5.1/elpa/dash-201=
51021.113:/home/ap4y/github/swift-mode/.cask/24.5.1/elpa/pkg-info-20150517.=
443:/home/ap4y/github/swift-mode/.cask/24.5.1/elpa/epl-20150517.433:/home/a=
p4y/github/swift-mode/.cask/24.5.1/elpa/let-alist-1.0.4:/home/ap4y/github/s=
wift-mode/.cask/24.5.1/elpa/s-20150924.406:/usr/share/emacs/24.5/lisp:/usr/=
share/emacs/24.5/lisp/vc:/usr/share/emacs/24.5/lisp/url:/usr/share/emacs/24=
.5/lisp/textmodes:/usr/share/emacs/24.5/lisp/progmodes:/usr/share/emacs/24.=
5/lisp/play:/usr/share/emacs/24.5/lisp/org:/usr/share/emacs/24.5/lisp/nxml:=
/usr/share/emacs/24.5/lisp/net:/usr/share/emacs/24.5/lisp/mh-e:/usr/share/e=
macs/24.5/lisp/mail:/usr/share/emacs/24.5/lisp/leim:/usr/share/emacs/24.5/l=
isp/language:/usr/share/emacs/24.5/lisp/international:/usr/share/emacs/24.5=
/lisp/gnus:/usr/share/emacs/24.5/lisp/eshell:/usr/share/emacs/24.5/lisp/erc=
:/usr/share/emacs/24.5/lisp/emulation:/usr/share/emacs/24.5/lisp/emacs-para=
llel:/usr/share/emacs/24.5/lisp/emacs-lisp:/usr/share/emacs/24.5/lisp/cedet=
:/usr/share/emacs/24.5/lisp/calendar:/usr/share/emacs/24.5/lisp/calc:/usr/s=
hare/emacs/24.5/lisp/obsolete
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Swift

Minor modes in effect:
  tooltip-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t

Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
delete-backward-char: Text is read-only

Load-path shadows:
None found.

Features:
(shadow sort gnus-util mail-extr emacsbug message format-spec rfc822 mml
mml-sec mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev
gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util
help-fns mail-prsvr mail-utils vc-git swift-mode edmacro kmacro easymenu
derived pcase smie cl-loaddefs cl-lib comint ansi-color ring rx
time-date tooltip electric uniquify ediff-hook vc-hooks lisp-float-type
mwheel x-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list newcomment lisp-mode prog-mode register page menu-bar
rfn-eshadow timer select scroll-bar mouse jit-lock font-lock syntax
facemenu font-core frame cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese hebrew greek romanian slovak
czech european ethiopic indian cyrillic chinese case-table epa-hook
jka-cmpr-hook help simple abbrev minibuffer nadvice loaddefs button
faces cus-face macroexp files text-properties overlay sha1 md5 base64
format env code-pages mule custom widget hashtable-print-readable
backquote make-network-process dbusbind gfilenotify dynamic-setting
system-font-setting font-render-setting move-toolbar gtk x-toolkit x
multi-tty emacs)

Memory information:
((conses 16 80479 5190)
 (symbols 48 18853 0)
 (miscs 40 39 110)
 (strings 32 13296 5273)
 (string-bytes 1 380693)
 (vectors 16 10443)
 (vector-slots 8 396412 6566)
 (floats 8 66 65)
 (intervals 56 185 0)
 (buffers 960 12)
 (heap 1024 41403 1158))

--=-=-=--