如何开始使用Emacs + fcsh + Flex3?

时间:2010-02-10 19:41:18

标签: flex actionscript-3 emacs fcsh

我有一些合理的emacs-fu,我知道如何使用Flash Builder IDE在Flex / Actionscript中工作,但是我想转而使用Emacs来完成我的大部分编码而不是flash建设者。但这会带来一些问题,即我不确定如何从fcsh-mode命令行编译我的flex项目。

以下是我的设置大纲:

  • 我的项目通常依赖于已编译的第三方.swc文件的组合。
  • 我使用一些内部库作为FB中的Actionscript Library Projects。
  • 我偶尔会重新编​​译依赖项,但我可能会在极少数时间内继续在FB中执行此操作。
  • 每个Flex应用程序项目都包含MXML和ActionScript源的混合。

我从来没有以这种方式使用命令行编译器,所以我对如何启动感到有些困惑。当人们在'网上谈论fcsh时,我一直在阅读compile 1,但这只是给了我fcsh: Target 1 not found,我认为这意味着我必须预先运行'正确'的编译。但是没有一个网站能够触及那些神秘的咒语。

因此,这里的基本问题是:从打开动作脚本或MXML文件到成功编译文件开始,最小的完整步骤是什么?

2 个答案:

答案 0 :(得分:3)

这就是事情 - fcsh并不是真正用于构建项目,而是用于增量开发。

找出fcsh的最好方法是首先学习如何在命令行中使用mxmlc和compc。使用这些工具编译项目所需的详细程度会在某些时候激怒你,所以你需要像上面评论的那样制作一个蚂蚁任务或类似工具。

因此,在设置了ant项目后,您将开始意识到,即使您完成了所有设置,但重新编译仍然需要比使用Flex Builder时更长的时间。原因是渐进式编译 - FB实际上并没有重新编译所有内容,它只是重新编译依赖关系树的闭包,它会挂掉您更改的文件。

输入fcsh。它基本上是mxmlc的黑客版本,包含FB使用的相同增量编译代码。它将部分编译结果存储到索引结果集中,这就是“编译1”所指的内容;它意味着“重建与以前相同的东西,但只重新编译改变的东西”。

好的,那是事实的一部分,所以现在是意见:不要打扰。虽然fcsh可以大大加快重新编译一个蓬松的源代码树,但更好的答案是“不要那样组织你的代码”。我个人认为,更仔细地划分源代码以构建SWC或模块,并设置多个独立的单独编译库,它们之间具有接口偏差的依赖关系是一个更好的路径。然后,当你重新编译时,你通常要么只是重建库,要么重建应用程序,而不是所有其他东西。对我来说,fcsh在编译过程中需要太多“思考”,而基于库的项目层次结构几乎同样快,我对调用M-x编译更加“愚蠢”。

OH!别忘了“fdb”。它主要是gdb兼容的,所以M-x gdb实际上工作得很好,或者至少在我还没参与的时候就习惯了。 :-D

答案 1 :(得分:0)

请参阅 http://nisheet.wordpress.com/category/emacs/ 要么 http://anirudhs.chaosnet.org/code/ani-fcsh.el.html创建.emacs文件然后(可选)使用以下内容添加actionscript-mode:

要编译,请参阅:http://anirudhs.chaosnet.org/blog/2008.03.26.html

;;; as3-mode.el --- A simple mode for editing Actionscript 3 files

;; Copyright (C) 2008 Austin Haas

;; Author: Austin Haas
;; Keywords: language modes

;; Tabbing stolen from: Aemon Cannon, http://github.com/aemoncannon/as3-mode/tree/master/as3-mode.el
;; Copyright (C) 2007 Aemon Cannon

;; This file 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 2, or (at your option)
;; any later version.

;; This file 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 GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;;; Commentary:
;;
;;------------------
;;; TODO

;; Imenu (imenu-generic-expression or imenu-create-index-function)

;;------------------

;;; Code:

(require 'font-lock)
(eval-when-compile
  (require 'regexp-opt))

(defconst actionscript-mode-version "7.0"
  "Actionscript Mode version number.")

(defgroup actionscript nil
  "Major mode for editing Actionscript code."
  :group 'languages)

(defvar actionscript-mode-syntax-table nil
  "Syntax table used in actionscript-mode buffers.")

(if actionscript-mode-syntax-table
        ()
    (setq actionscript-mode-syntax-table (make-syntax-table))
  (modify-syntax-entry ?_  "w"     actionscript-mode-syntax-table)
;;  (modify-syntax-entry ?_  "_"     actionscript-mode-syntax-table)
  (modify-syntax-entry ?$  "w"     actionscript-mode-syntax-table)
  (modify-syntax-entry ?\\ "\\"    actionscript-mode-syntax-table)
  (modify-syntax-entry ?+  "."     actionscript-mode-syntax-table)
  (modify-syntax-entry ?-  "."     actionscript-mode-syntax-table)
  (modify-syntax-entry ?=  "."     actionscript-mode-syntax-table)
  (modify-syntax-entry ?%  "."     actionscript-mode-syntax-table)
  (modify-syntax-entry ?<  "."     actionscript-mode-syntax-table)
  (modify-syntax-entry ?>  "."     actionscript-mode-syntax-table)
  (modify-syntax-entry ?&  "."     actionscript-mode-syntax-table)
  (modify-syntax-entry ?|  "."     actionscript-mode-syntax-table)
  (modify-syntax-entry ?\' "\""    actionscript-mode-syntax-table)
  (modify-syntax-entry ?\240 "."   actionscript-mode-syntax-table)
    (modify-syntax-entry ?/  ". 124b" actionscript-mode-syntax-table)
    (modify-syntax-entry ?*  ". 23"   actionscript-mode-syntax-table)
  (modify-syntax-entry ?\n "> b"  actionscript-mode-syntax-table)
  (modify-syntax-entry ?\^m "> b" actionscript-mode-syntax-table))

(defvar actionscript-mode-map ()
  "Keymap used in actionscript-mode buffers.")

(if actionscript-mode-map
        ()
    (setq actionscript-mode-map (make-sparse-keymap))
    (define-key actionscript-mode-map [(control meta a)] 'as-beginning-of-defun)
    (define-key actionscript-mode-map [(control meta e)] 'as-end-of-defun)
    (define-key actionscript-mode-map [(control meta h)] 'as-mark-defun)
    (define-key actionscript-mode-map "\C-c\C-c" 'comment-region)
    (define-key actionscript-mode-map "\C-c\C-u" 'uncomment-region))

(defcustom actionscript-mode-hook nil
  "*Hook called by `actionscript-mode'."
  :type 'hook
  :group 'actionscript)

;; Preprocessor directives (for cpp, not Actionscript).
(defconst preprocessor-kwds
    '("#include" "#define" "#else" "#endif" "#ifdef" "#ifndef"))

;; Constants
(defconst actionscript-constant-kwds 
    '("true" "false" "null" "undefined" "NaN" "Infinity" "-Infinity"))

;; Global funcs
(defconst actionscript-global-funcs
  '("Array" "Boolean" "decodeURI" "decodeURIComponent" "encodeURI" 
        "encodeURIComponent" "escape" "int" "isFinite" "isNaN" "isXMLName"
        "Number" "Object"   "parseFloat" "parseInt" "String" "trace" "uint" 
        "unescape" "XML" "XMLList"))

;; Top Level Classes
(defconst actionscript-global-classes
    '("ArgumentError" "arguments" "Array" "Boolean" "Class" "Date"
        "DefinitionError" "Error" "EvalError" "Function" "int" "Math"
        "Namespace" "Number" "Object" "QName" "RangeError" "ReferenceError"
        "RegExp" "SecurityError" "String" "SyntaxError" "TypeError" "uint"
        "URIError" "VerifyError" "XML" "XMLList"))

;; Global props
(defconst actionscript-global-props
    '("this"))

;; Operators
(defconst actionscript-symbol-operators
    '("+" "+=" "[]" "=" "&" "&=" "<<" "<<=" 
        "~" "|" "|=" ">>" ">>=" ">>>" ">>>=" 
        "^" "^=" "/*" "*/" "," "?:" "--" "/" 
        "/=" "." "==" ">" ">=" "++" "!=" "<>" 
        "<" "<=" "//" "&&" "!" "||" "%" "%=" 
        "*" "*=" "{}" "()" "===" "!==" "\"" 
        "-" "-=" ":"))

(defconst actionscript-word-operators
    '("as" "is" "instanceof" "new" "typeof" "void"))

;; Declaration specifier keywords.
(defconst actionscript-specifier-kwds
  '("override" "instrinsic" "private" "protected" "public" "static" "dynamic"))

;; Class/struct declaration keywords.
(defconst actionscript-class-kwds 
    '("class" "interface"))

(defconst actionscript-package-kwds
    '("package"))

;; Keywords introducing other declaration-level constructs.
(defconst actionscript-other-decl-kwds
    '("import"))

;; Variable and Function declarations
(defconst actionscript-other-decl-2-kwds
    '("var" "function" "const"))

;; Keywords that occur in declaration-level constructs.
(defconst actionscript-decl-level-kwds 
    '("extends" "implements"))

;; Conditionals
;; *Not sure if "catch" should be here,
;; but it's assumed to be here for the actionscript-conditional-key.
(defconst actionscript-conditional-kwds
    '("for" "for each" "if" "while" "switch" "catch"))

;; Statement keywords followed directly by a block.
(defconst actionscript-block-stmt-1-kwds
  '("do" "else" "finally" "try"))

;; Statement keywords followed by an expression or nothing.
(defconst actionscript-simple-stmt-kwds
  '("break" "continue" "return" "throw"))

;; Keywords introducing labels in blocks.
(defconst actionscript-label-kwds 
    '("case" "default"))

;; Keywords that can occur anywhere in expressions.
(defconst actionscript-expr-kwds 
    '("super"))

;; Other keywords that we haven't grouped properly.
(defconst actionscript-other-kwds
    '("delete" "get" "set" "with"))

;;  (defconst actionscript-builtin-props
;;  (regexp-opt
;;   (append actionscript-object-props
;;                   actionscript-function-props
;;                   actionscript-array-props
;;                   actionscript-string-props
;;                   actionscript-date-props
;;                   actionscript-number-props
;;                   actionscript-math-props)))

;; (defconst actionscript-builtin-funcs(regexp-opt
;;   (append actionscript-global-funcs
;;                   actionscript-math-funcs
;;                   actionscript-array-funcs
;;                   actionscript-date-funcs)))

(defconst actionscript-keywords
    (regexp-opt
     (append actionscript-constant-kwds
                     actionscript-global-funcs
                     actionscript-global-classes
                     actionscript-global-props
                     actionscript-specifier-kwds
                     actionscript-class-kwds
                     actionscript-package-kwds
                     actionscript-other-decl-kwds
                     actionscript-other-decl-2-kwds
                     actionscript-decl-level-kwds
                     actionscript-conditional-kwds
                     actionscript-block-stmt-1-kwds
                     actionscript-simple-stmt-kwds
                     actionscript-label-kwds
                     actionscript-expr-kwds
                     actionscript-other-kwds) 'words))

(defconst actionscript-identifier-re "[a-zA-Z_$][a-zA-Z0-9_$]*"
    "Regexp to match any valid identifier in actionscript.")

(defcustom actionscript-mode-hook nil
  "*Hook called by `actionscript-mode'."
  :type 'hook
  :group 'actionscript)

(defcustom actionscript-font-lock-level 2
    "*What level of syntax highlighting do we want. 1-3"
    :type '(radio (const :tag "Only keywords." 1)
                    (const :tag "Keywords and contextual tags." 2)
                    (const :tag "All of the above plus all of Actionscript's builtin classes. (not implemented)" 3))
    :group 'actionscript)

;;;; Faces -------------------------------------------------------------------

(defvar actionscript-font-lock-default-face 'actionscript-font-lock-default-face)

(let ((red "#a35757")
            (green "#7ac470")
            (yellow "#dfe14e")
            (orange "#ef6d22")
            (blue "#5083b2")
            (magenta "#b781ac")
            (cyan "#b0b5d2")
            (white "#f0f0f0"))

    (defface actionscript-preprocessor-kwds-face 
            `((t (:foreground ,yellow)))
        "*Face for preprocesor directives."
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-constant-kwds-face 
            `((t (:foreground ,cyan)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-global-funcs-face 
            `((t (:foreground ,red)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-global-classes
            `((t (:foreground ,blue)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-global-props-face 
            `((t (:foreground ,blue)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-operators-face 
            `((t (:foreground ,yellow)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-specifier-kwds-face 
            `((t (:foreground ,magenta)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-package-kwds-face 
            `((t (:foreground ,yellow)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-class-kwds-face 
            `((t (:foreground ,yellow)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-other-decl-kwds-face 
            `((t (:foreground ,yellow)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-other-decl-2-kwds-face 
            `((t (:foreground ,blue)))
        "* function, var"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-decl-level-kwds-face 
            `((t (:foreground ,yellow)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-conditional-kwds-face
            `((t (:foreground ,yellow)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-block-stmt-1-kwds-face
            `((t (:foreground ,yellow)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-simple-stmt-kwds-face
            `((t (:foreground ,yellow)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-label-kwds-face
            `((t (:foreground ,yellow)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-expr-kwds-face
            `((t (:foreground ,red)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-other-kwds-face
            `((t (:foreground ,red)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-package-name-face
            `((t (:foreground ,green)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-class-name-face
            `((t (:foreground ,cyan)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-function-name-face
            `((t (:foreground ,green)))
        "*"
        :group 'actionscript-faces :group 'faces)

    (defface actionscript-variable-name-face
            `((t (:foreground ,cyan)))
        "*"
        :group 'actionscript-faces :group 'faces)
    )

(defconst actionscript-font-lock-keywords-1
     ;; The following only highlight specific words that exist in the language.
   (list
        `(,(regexp-opt preprocessor-kwds 'words) 0 'actionscript-preprocessor-kwds-face)
        `(,(regexp-opt actionscript-constant-kwds 'words) 0 'actionscript-constant-kwds-face)
        `(,(regexp-opt actionscript-global-funcs 'words) 0 'actionscript-global-funcs-face)
        `(,(regexp-opt actionscript-global-props 'words) 0 'actionscript-global-props-face)
;;      `(,(regexp-opt actionscript-symbol-operators) 0 'actionscript-operators-face)
        `(,(regexp-opt actionscript-word-operators 'words) 0 'actionscript-operators-face)
        `(,(regexp-opt actionscript-specifier-kwds 'words) 0 'actionscript-specifier-kwds-face)
        `(,(regexp-opt actionscript-class-kwds 'words) 0 'actionscript-class-kwds-face)
        `(,(regexp-opt actionscript-package-kwds 'words) 0 'actionscript-package-kwds-face)
        `(,(regexp-opt actionscript-other-decl-kwds 'words) 0 'actionscript-other-decl-kwds-face)
        `(,(regexp-opt actionscript-other-decl-2-kwds 'words) 0 'actionscript-other-decl-2-kwds-face)
        `(,(regexp-opt actionscript-decl-level-kwds 'words) 0 'actionscript-decl-level-kwds-face)
        `(,(regexp-opt actionscript-conditional-kwds 'words) 0 'actionscript-conditional-kwds-face)
        `(,(regexp-opt actionscript-block-stmt-1-kwds 'words) 0 'actionscript-block-stmt-1-kwds-face)
        `(,(regexp-opt actionscript-simple-stmt-kwds 'words) 0 'actionscript-simple-stmt-kwds-face)
        `(,(regexp-opt actionscript-label-kwds 'words) 0 'actionscript-label-kwds-face)
        `(,(regexp-opt actionscript-expr-kwds 'words) 0 'actionscript-expr-kwds-face)
        `(,(regexp-opt actionscript-other-kwds 'words) 0 'actionscript-other-kwds-face))
    "Subdued level highlighting for Actionscript mode.")

(defconst actionscript-font-lock-keywords-2
  (append
   actionscript-font-lock-keywords-1
     ;;;; The rules in this section highlight words in the buffer by determining their context.
     (list 
        ;; Fontify package names in import directives.
        ;; TODO: support '*' as the last symbol in the package name.
        (list (concat (regexp-opt actionscript-other-decl-kwds 'words) "[ \t]*\\(?:" actionscript-identifier-re "\\.\\)*\\(" actionscript-identifier-re "\\)?")
                    '(2 'actionscript-class-name-face nil t)
                    (list (concat "[ \t]*\\(" actionscript-identifier-re "\\)\\.") '(goto-char (match-end 1)) '(goto-char (match-end 0)) '(1 'actionscript-package-name-face nil t)))

        ;; Fontify package names.
        (list (concat (regexp-opt (append actionscript-package-kwds) 'words) "[ \t]*\\(" actionscript-identifier-re "\\)?")
                    '(2 'actionscript-package-name-face nil t))

        ;; Fontify class names.
        (list (concat (regexp-opt (append actionscript-class-kwds actionscript-decl-level-kwds) 'words) "[ \t]*\\(" actionscript-identifier-re "\\)?")
                    '(2 'actionscript-class-name-face nil t))

        ;; Function names.
        (list (concat "\\<function\\>[ \t\n]+\\(?:\\(?:get\\|set\\)[ \t\n]+\\)?\\(?:\\(" actionscript-identifier-re "\\)\\)?")
                    '(1 'actionscript-function-name-face nil t))

        ;; The 'in' in 'for..in.'
        (list (concat "\\<for\\>[ \t\n]*([ \t\n]*\\(?:var[ \t\n]+\\)?" actionscript-identifier-re "[ \t\n]*\\(?::[ \t\n]*\\([a-zA-Z0-9_$*]*\\)\\)?[ \t\n]+\\(in\\)[ \t\n]+")
                    '(2 'actionscript-other-kwds-face nil t))

        ;; The 'each' and the 'in' in 'for each..in.'
;;      (list (concat "\\<for\\>[ \t\n]+\\(?:\\(each\\)[ \t\n]*\\)([ \t\n]*\\(?:var[ \t\n]+\\)?" actionscript-identifier-re "[ \t\n]*\\(?::[ \t\n]*\\([a-zA-Z0-9_$*]*\\)\\)?[ \t\n]+\\(in\\)[ \t\n]+")
;;                  '(1 'actionscript-other-kwds-face nil t)
;;                  '(3 'actionscript-other-kwds-face nil t))

        ;; Local variables.
        (list (concat "\\<var\\>"
                                    "\\([ \t]*"
                                    actionscript-identifier-re
                                    "\\)")
                    ;; Fontify each declaration item.
                    '(font-lock-match-c-style-declaration-item-and-skip-to-next
                        ;; Start and finish with point after the type specifier.
                        (goto-char (match-beginning 1))
                        (goto-char (match-beginning 1))
                        (1 'actionscript-variable-name-face)))

        ;; Objects and their functions
        ;; package(s) class property
        ;; TODO: We'd like to be able to distinguish true class names from a variable, so
        ;;       that String.parse() would look different than mystring.parse().
        ;;      -We might also want to distinguish local function calls, like parse().
;;      (list (concat "\\<" "\\(?:[A-Za-z_]\\sw*\\.\\)*" "\\(?:[A-Za-z_]\\sw*\\.\\)" "\\([A-Za-z_]*\\)")
;;                  '(1 'actionscript-function-name-face))
    ))
    "Medium level highlighting for Actionscript mode.")

(defconst actionscript-font-lock-keywords-3
  (append
   actionscript-font-lock-keywords-2
   (list
        ;; TODO: Add all the builtin objects in Actionscript.

        ;; Builtin props.
;;      (list actionscript-builtin-props 1 'actionscript-builtin-props-face)

        ;; Builtin funcs.
;;      (list actionscript-builtin-funcs 1 'actionscript-builtin-funcs-face)

    ))
  "Gaudy level highlighting for Actionscript mode.")

;; --------------------------------------------------------------------------------

(defun as-get-function-re(&optional function-name)
    "Returns a regular expression that will match the function signature
containing the supplied function-name. If function-name is omitted,
the regexp will match any function."
    (unless function-name
        (setq function-name actionscript-identifier-re))
    (let ((visibility-kwd (regexp-opt '("public" "protected" "private") nil))
                (other-kwd (regexp-opt '("final" "static" "override") nil))
                (get-set-kwd (regexp-opt '("get" "set") nil)))
        (concat "\\(?:^[ \t\n]*\\)"                                          ; Start of line, followed by any amount of whitespace.
                        "\\(?:\\(" visibility-kwd "\\|" other-kwd "\\)[ \t\n]+\\)?"  ; (1) Any of the optional keywords, which must be followed by whitespace.
                        "\\(?:\\(" visibility-kwd "\\|" other-kwd "\\)[ \t\n]+\\)?"  ; (2) A second optional keyword, which must be followed by whitespace.
                        "\\<function\\>"                                             ; 'function' keyword.
                        "[ \t\n]+"                                                   ; Mandatory whitespace.
                        "\\(?:" get-set-kwd "[ \t\n]+\\)?"                           ; Optional get/set keyword, which must be followed by whitespace.
                        "\\(" function-name "\\)"                                    ; (3) Function name.
                        "[ \t\n]*"                                                   ; Optional whitespace.
                        "("                                                          ; Opening paren for function parameters.
                        "[ \t\n]*"                                                   ; Optional whitespace.
                        "\\([\"a-zA-Z\-0-9_$*,:= \t\n]*?\\(?:\\.\\.\\.[a-zA-Z\-0-9_$]+\\)?\\)"           ; (4) Function parameters, including any trailing '...args'.
                        ")"                                                          ; Closing paren for function parameters.
                        "[ \t\n]*"                                                   ; Optional whitespace.
                        "\\(?::[ \t\n]*\\(" actionscript-identifier-re "\\|*\\)\\)?"    ; (5) Optional return value type specifier.
                        "[ \t\n]*"                                                   ; Optional whitespace.
                        "{")))                                                       ; Opening brace for function body.

(defconst as-function-re (as-get-function-re)
    "A regexp that matches a function signature in Actionscript 3.0.")

(defun as-get-attribute-re(&optional attribute-name)
    "Returns a regular expression that will match the class attribute
definition containing the supplied attribute-name. If attribute-name
is omitted, the regexp will match any class attribute."
    (unless attribute-name
        (setq attribute-name actionscript-identifier-re))
    (let ((visibility-kwd (regexp-opt '("public" "protected" "private") nil))
                (var-kwd (regexp-opt '("var" "const") nil))
                (other-kwd "static"))
        (concat "\\(?:^[ \t\n]*\\)"                                          ; Start of line, followed by any amount of whitespace.
                        "\\(?:\\(" visibility-kwd "\\|" other-kwd "\\)[ \t\n]+\\)?"  ; (1) Any of the optional keywords, which must be followed by whitespace.
                        "\\(?:\\(" visibility-kwd "\\|" other-kwd "\\)[ \t\n]+\\)?"  ; (2) A second optional keyword, which must be followed by whitespace.
                        "\\<\\(" var-kwd "\\)\\>"                                    ; (3) var keyword.
                        "[ \t\n]+"                                                   ; Mandatory whitespace.
                        "\\(" attribute-name "\\)"                                   ; (4) Attribute name.
                        "[ \t\n]*"                                                   ; Optional whitespace.
                        "\\(?::[ \t\n]*\\(" actionscript-identifier-re "*\\)\\)?"    ; (5) Optional type specifier.
                        )))

(defconst as-attribute-re (as-get-attribute-re)
    "A regexp that matches a class attribute definition in Actionscript 3.0.")

;; Support for imenu
(defvar as-imenu-generic-expression
    `((nil ,as-function-re 3)))

(defun as-imenu-init (mode-generic-expression)
  (setq imenu-generic-expression mode-generic-expression
                imenu-case-fold-search nil))

(defun as-get-beginning-of-defun()
    ;; Returns the position.
    (save-excursion
        (when   (re-search-backward as-function-re nil t)
            (match-beginning 1))))

(defun as-get-end-of-defun()
    ;; This only works if we are inside a defun.
    (save-excursion
        (when   (re-search-backward as-function-re nil t)
            (goto-char (match-end 0))
            ;; Move back a char, so that point is right on the opening
            ;; brace.
            (backward-char)
            (forward-list)
            (point))))

(defun as-get-end-of-defun2()
    ;; This should work if we are not inside any defuns.
    (save-excursion
        (beginning-of-line) ; hack, in case point is currently inside a function sig.
        (when   (re-search-forward as-function-re nil t)
            (goto-char (match-end 0))
            ;; Move back a char, so that point is right on
            ;; the opening brace.
            (backward-char)
            (forward-list)
            (point))))

(defun as-beginning-of-defun()
    (interactive)
    (let ((pos (as-get-beginning-of-defun)))
        (if pos
                (goto-char pos)
                (message "Can't find any functions."))))

(defun as-inside-defun?()
    (let ((cur (point))
                (start (as-get-beginning-of-defun))
                (end (as-get-end-of-defun)))
        (and start
                 end
                 (> cur start)
                 (< cur end))))

(defun as-end-of-defun()
    (interactive)
    (if (as-inside-defun?)
            (goto-char (as-get-end-of-defun))
        (let ((pos (as-get-end-of-defun2)))
            (if pos
                    (goto-char pos)
                (message "Can't find any functions.")))))

(defun as-mark-defun()
    (interactive)
    (let ((start (as-get-beginning-of-defun))
                (end (as-get-end-of-defun)))
        (if (not (or start end))
                (message "Can't find any functions.")
            (set-mark end)
            (goto-char start)
            (beginning-of-line))))

;; --------------------------------------------------------------------------------

;; Indentation (by Aemon Cannon: http://github.com/aemoncannon/as3-mode/tree/master/as3-mode.el)

(defun actionscript-indent-line ()
  "Indent current line of As3 code."
  (interactive)
  (indent-line-to (max 0 (as3-calculate-indentation))))

(defun as3-calculate-indentation ()
  "Return the column to which the current line should be indented."
  (save-excursion
    (as3-maybe-skip-leading-close-delim)
    (let ((pos (point)))
      (beginning-of-line)
      (if (not (search-backward-regexp "[^\n\t\r ]" 1 0))
   0
  (progn
   (as3-maybe-skip-leading-close-delim)
   (+ (current-indentation) (* standard-indent (as3-count-scope-depth (point) pos))))))))

(defun as3-maybe-skip-leading-close-delim ()
  (beginning-of-line)
  (forward-to-indentation 0)
  (if (looking-at "\\s)")
      (forward-char)
    (beginning-of-line)))

(defun as3-face-at-point (pos)
  "Return face descriptor for char at point."
  (plist-get (text-properties-at pos) 'face))

(defun as3-count-scope-depth (rstart rend)
  "Return difference between open and close scope delimeters."
  ;;Attempting Steve Yegge's solution..
  ;; (save-excursion
  ;; (let ((result (parse-partial-sexp rstart rend)))
  ;; (if (or (nth 3 result) (nth 4 result) (nth 7 result))
  ;;   0
  ;;  (nth 0 result)))))
  (save-excursion
    (goto-char rstart)
    (let ((open-count 0)
          (close-count 0)
          opoint)
      (while (and (< (point) rend)
                  (progn (setq opoint (point))
                         (re-search-forward "\\s)\\|\\s(" rend t)))
        (if (= opoint (point))
            (forward-char 1)
          (cond
           ;; Don't count if in string or comment.
           ((as3-face-at-point (- (point) 1)))
           ((looking-back "\\s)")
            (incf close-count))
           ((looking-back "\\s(")
            (incf open-count))
           )))
      (- open-count close-count))))

;; --------------------------------------------------------------------------------

;;;###autoload
(defun actionscript-mode ()
  "Major mode for editing Actionscript files.
\\{actionscript-mode-map}"
    (interactive)
    (kill-all-local-variables)
    (use-local-map actionscript-mode-map)
    (setq major-mode 'actionscript-mode
                mode-name "Actionscript")
;;              local-abbrev-table actionscript-mode-abbrev-table)
  (make-local-variable 'indent-line-function)
  (setq indent-line-function 'actionscript-indent-line)
    (set-syntax-table actionscript-mode-syntax-table)
  (make-local-variable 'parse-sexp-ignore-comments)
  (setq parse-sexp-ignore-comments t)
  (make-local-variable 'comment-start)
    (setq comment-start "//")
  (make-local-variable 'comment-start-skip)
  (setq comment-start-skip "\\(//+\\|/\\*+\\)\\s *")
  (make-local-variable 'font-lock-defaults)
  (setq font-lock-defaults
        `((,(cond 
                         ((= actionscript-font-lock-level 1) 'actionscript-font-lock-keywords-1)
                         ((= actionscript-font-lock-level 2) 'actionscript-font-lock-keywords-2)
                         ((= actionscript-font-lock-level 3) 'actionscript-font-lock-keywords-3)))
          nil nil))
    (run-mode-hooks 'actionscript-mode-hook))

;; We need to make an adjustment to hideshow to work properly with AS syntax.
(add-to-list 'hs-special-modes-alist '(actionscript-mode "{" "}" "/[*/]" nil hs-c-like-adjust-block-beginning))

(provide 'actionscript-mode)

;; For testing
(defun reload-actionscript-mode ()
    (interactive)
    (with-current-buffer (get-buffer "actionscript-mode.el")
        (eval-buffer))
    (with-current-buffer (get-buffer "test.as")
        (actionscript-mode)
        (message "actionscript-mode reloaded.")))

(define-key global-map [f5] 'reload-actionscript-mode)