doomemacs/contrib/unityjs-mode.el

321 lines
44 KiB
EmacsLisp
Raw Normal View History

2015-04-01 03:24:23 +08:00
;;; unityjs-mode.el --- Major mode for editing Unity JavaScript
;; Author: Juan Sebastian Muñoz <naruse@gmail.com>
;; Identation took from: http://cvs.savannah.gnu.org/viewvc/*checkout*/emacs/lisp/progmodes/js.el?root=emacs
;; Authors:
;; Karl Landstrom <karl.landstrom@brgeight.se>
;; Daniel Colascione <dan.colascione@gmail.com>
;;
;; Version: 1
;; Date: 2010-01-08
;; Keywords: Unity3D, Unity Javascript.
;; This file is licensed as GPL, 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 file comes 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.
(defvar unityjs-mode-hook nil)
(defvar unityjs-mode-map
(let ((unityjs-mode-map (make-sparse-keymap)))
(define-key unityjs-mode-map "\C-j" 'newline-and-indent)
unityjs-mode-map)
"Keymap for UnityJS major mode")
(add-to-list 'auto-mode-alist '("\\.js\\'" . unityjs-mode))
;; Word Highlighting
(defconst unityjs-font-lock-keywords-1
(list
'("\\<\\(A\\(?:bs\\|c\\(?:ceptDrag\\|os\\)\\|dd\\(?:BinaryData\\|C\\(?:lip\\|o\\(?:lor\\|mponent\\(?:Menu\\)?\\|ntrol\\)\\|ursorRect\\)\\|DefaultControl\\|E\\(?:vent\\|xplosionForce\\)\\|F\\(?:ield\\|loat\\|orce\\(?:AtPosition\\)?\\)\\|Key\\|M\\(?:atrix\\|ixingTransform\\)\\|ObjectToAsset\\|Relative\\(?:\\(?:Forc\\|Torqu\\)e\\)\\|Torque\\|Vector\\)?\\|l\\(?:locateViewID\\|tDirectorySeparatorChar\\)\\|n\\(?:gle\\(?:Axis\\)?\\|i\\(?:mation\\(?:BlendMode\\(?:\\.\\(?:Additive\\|Blend\\)\\)?\\|C\\(?:lip\\(?:CurveData\\)?\\|urve\\)\\|Event\\|State\\|Utility\\)?\\|sotropicFiltering\\(?:\\.\\(?:\\(?:Dis\\|\\(?:Force\\)?En\\)able\\)\\)?\\)\\)\\|pp\\(?:l\\(?:ication\\|y\\(?:ModifiedProperties\\)?\\)\\|roximately\\)\\|rr\\(?:ay\\|owCap\\)\\|s\\(?:in\\|set\\(?:Bundle\\(?:Request\\)?\\|Database\\|Importer\\|P\\(?:athToGUID\\|ostprocessor\\)\\)\\|yncOperation\\)\\|tan2?\\|udio\\(?:Clip\\|Importer\\(?:Format\\(?:\\.\\(?:Compressed\\|Native\\)\\)?\\)?\\|Listener\\|Source\\|VelocityUpdateMode\\(?:\\.\\(?:Auto\\|Dynamic\\|Fixed\\)\\)?\\)\\|wake\\)\\|B\\(?:e\\(?:ep\\|gin\\(?:Area\\|G\\(?:UI\\|roup\\)\\|Horizontal\\|LayoutGroup\\|S\\(?:ample\\|crollView\\)\\|ToggleGroup\\|Vertical\\|Windows\\)?\\|haviour\\)\\|itStream\\|l\\(?:end\\|it\\(?:MultiTap\\)?\\)\\|o\\(?:neWeight\\|unds\\|x\\(?:Collider\\)?\\)\\|r\\(?:eak\\|ingWindowTo\\(?:Back\\|Front\\)\\|o\\(?:adcastMessage\\|wseURL\\)\\)\\|u\\(?:ild\\(?:AssetBundle\\(?:ExplicitAssetNames\\|Options\\(?:\\.\\(?:Co\\(?:\\(?:llectDependencie\\|mpleteAsset\\)s\\)\\|DeterministicAssetBundle\\)\\)?\\)?\\|Options\\(?:\\.\\(?:AutoRunPlayer\\|BuildAdditionalStreamedScenes\\|Development\\|ShowBuiltPlayer\\)\\)?\\|P\\(?:ipeline\\|layer\\)\\|Target\\(?:\\.\\(?:DashboardWidget\\|Standalone\\(?:OSX\\(?:Intel\\|PPC\\|Universal\\)\\|Windows\\)\\|WebPlayer\\(?:Streamed\\)?\\)\\)?\\)\\|tton\\)\\)\\|C\\(?:a\\(?:l\\(?:c\\(?:Height\\|LineTranslation\\|MinMaxWidth\\|S\\(?:\\(?:creenS\\)?ize\\)\\|ulate\\(?:FrustumPlanes\\|TransformPath\\)\\)\\|lbackFunction\\)\\|mera\\(?:ClearFlags\\(?:\\.\\(?:Depth\\|Nothing\\|S\\(?:kybox\\|olidColor\\)\\)\\)?\\)?\\|n\\(?:StreamedLevelBeLoaded\\|cel\\(?:Invoke\\|Quit\\)\\)\\|p\\(?:suleCollider\\|tureScreenshot\\)\\)\\|eil\\(?:ToInt\\)?\\|h\\(?:aracter\\(?:Controller\\|Joint\\)\\|eck\\(?:\\(?:Capsul\\|Spher\\)e\\)\\)\\|l\\(?:amp\\(?:01\\)?\\|ear\\(?:C\\(?:amera\\|urves\\)\\|HostList\\|Log\\|P\\(?:articles\\|rogressBar\\)\\|SnapshotTarget\\)?\\|o\\(?:neComponent\\|se\\(?:Connection\\|stPo\\(?:int\\(?:OnBounds\\|To\\(?:Arc\\|Disc\\|PolyLine\\)\\)\\|werOfTwo\\)\\)?\\)\\)\\|o\\(?:l\\(?:l\\(?:ectDe\\(?:epHierarchy\\|pendencies\\)\\|i\\(?:der\\|sion\\(?:Flags\\(?:\\.\\(?:Above\\|Below\\|None\\|Sides\\)\\)?\\)?\\)\\)\\|or\\(?:Field\\)?\\)\\|m\\(?:bine\\(?:Instance\\|Meshes\\)?\\|p\\(?:areTag\\|onent\\|ress\\(?:Texture\\)?\\)\\)\\|n\\(?:cat\\|eCap\\|figurableJoint\\(?:Motion\\(?:\\.\\(?:Free\\|L\\(?:\\(?:imit\\|ock\\)ed\\)\\)\\)?\\)?\\|nect\\(?:ionTesterStatus\\(?:\\.\\(?:Error\\|P\\(?:rivateIP\\(?:\\(?:HasNATPunchT\\|NoNATPuncht\\)hrough\\)\\|ublicIP\\(?:IsConnectable\\|\\(?:NoServerStart\\|PortBlock\\)ed\\)\\)\\|Undetermined\\)\\)?\\)?\\|stantForce\\|t\\(?:a\\(?:ctPoint\\|ins\\(?:Key\\|Value\\)?\\)\\|extMenu\\|rollerColliderHit\\)\\)\\|py\\(?:Asset\\|F\\(?:ileOrDirectory\\(?:FollowSymlinks\\)?\\|rom\\)\\|PropertiesFromMaterial\\|Serialized\\)?\\|routine\\|s\\|untRemaining\\)\\|r\\(?:eate\\(?:Asset\\|EmptyPrefab\\|GameObjectWithHideFlags\\|Instance\\|Primitive\\|\\(?:Snapsho\\|TerrainGameObjec\\)t\\)?\\|oss\\(?:Fade\\(?:Queued\\)?\\)?\\)\\|u\\(?:be\\(?:Cap\\|map\\(?:Face\\(?:\\.\\(?:Negative[XYZ]\\|Positive[XYZ]\\)\\)?\\)?\\)\\|stomEditor\\)\\|ylinderCap\\)\\|D\\(?:e\\(?:bug\\|creaseLevel\\|g2Rad\\|l\\(?:ete\\(?:A\\(?:ll\\|sset\\)\\|\\(?:FileOrDirector\\|Ke\\)y\\)\\|taAngle\\)\\|pthTextureMode\\(?:\\.\\(?:Depth\\(?:Normals\\)?\\|None\\)\\)?\\|stroy\\(?:Immediate\\|PlayerObjects\\)?\\|tachChildren\\)\\|i\\(?:rectorySeparatorChar\\|s\\(?:c\\(?:onnect\\)?\\|play\\(?:Dialog\\(?:Complex\\)?\\|P\\(?:opupMenu\\|rogressBar\\)\\|Wizard\\)\\|tance\\(?:PointLine\\|To\\(?:Arc\\|Circle\\|Disc\\|\\(?:
'("\\<\\(S\\(?:e\\(?:rializedPropertyType\\.\\(?:C\\(?:\\(?:haracte\\|olo\\)r\\)\\|Enum\\|Float\\|Integer\\|LayerMask\\|ObjectReference\\|Rect\\|String\\|Vector[23]\\)\\|t\\(?:A\\(?:ctiveRecursively\\|nimation\\(?:\\(?:Clip\\|Event\\)s\\)\\)\\|Bo\\(?:ol\\|rderColor\\)\\|C\\(?:amera\\|ol\\(?:ors?\\|umn\\)\\|urve\\)\\|D\\(?:\\(?:ensi\\|ir\\)ty\\)\\|EditorCurve\\|F\\(?:loat\\|romToRotation\\)\\|G\\(?:enericData\\|lobal\\(?:Color\\|Float\\|Matrix\\|ShaderProperty\\|Texture\\|Vector\\)\\)\\|Heights\\|Int\\|L\\(?:evelPrefix\\|ookRotation\\)\\|M\\(?:\\(?:atri\\|inMa\\)x\\)\\|N\\(?:ameSmart\\|e\\(?:ighbors\\|xtControlName\\)\\)\\|ObjectEnabled\\|P\\(?:ass\\|ixels?\\|osition\\)\\|R\\(?:e\\(?:ceivingEnabled\\|placementShader\\|solution\\|vertBackfacing\\)\\|ow\\)\\|S\\(?:cope\\|endingEnabled\\|napshotTarget\\|tring\\)\\|T\\(?:RS\\|exture\\(?:Offset\\|Scale\\)?\\|riangles\\)\\|Ve\\(?:ctor\\|rtexCount\\)\\|Width\\)\\)\\|h\\(?:ader\\|ift\\|ow\\(?:Help\\(?:ForObject\\|Page\\)\\|Notification\\|Utility\\)?\\)\\|i\\(?:gn\\|m\\(?:\\(?:pleMov\\|ulat\\)e\\)\\|n\\)\\|k\\(?:in\\(?:Quality\\(?:\\.\\(?:Auto\\|Bone[124]\\)\\)?\\|nedMeshRenderer\\)\\|ybox\\)\\|l\\(?:e\\(?:[er]p\\)\\|ider\\)\\|mooth\\(?:Damp\\(?:Angle\\)?\\|Step\\|Tangents\\)\\|o\\(?:\\(?:ftJointLimi\\|r\\)t\\)\\|p\\(?:ace\\(?:\\.\\(?:Self\\|World\\)\\)?\\|hereC\\(?:ap\\|ollider\\)\\|ringJoint\\)\\|qr\\(?:Distance\\|t\\)\\|t\\(?:art\\(?:A\\(?:nimationMode\\|ssetEditing\\)\\|Coroutine\\|Drag\\)?\\|ep\\|op\\(?:A\\(?:llCoroutines\\|nimationMode\\|ssetEditing\\)\\|Coroutine\\)?\\|ring\\)\\|upportsRenderTextureFormat\\|y\\(?:ncLayer\\|stem\\(?:Info\\|Language\\(?:\\.\\(?:A\\(?:frikaans\\|rabic\\)\\|B\\(?:asque\\|\\(?:elarus\\|ulgar\\)ian\\)\\|C\\(?:atalan\\|hinese\\|zech\\)\\|D\\(?:\\(?:anis\\|utc\\)h\\)\\|E\\(?:nglish\\|stonian\\)\\|F\\(?:aroese\\|\\(?:inni\\|ren\\)sh\\)\\|G\\(?:erman\\|reek\\)\\|H\\(?:ebrew\\|ugarian\\)\\|I\\(?:celandic\\|\\(?:ndones\\|tal\\)ian\\)\\|Japanese\\|Korean\\|L\\(?:\\(?:atv\\|ithuan\\)ian\\)\\|Norwegian\\|Po\\(?:lish\\|rtuguese\\)\\|R\\(?:\\(?:oman\\|uss\\)ian\\)\\|S\\(?:erboCroatian\\|lov\\(?:ak\\|enian\\)\\|\\(?:pan\\|wed\\)ish\\)\\|T\\(?:hai\\|urkish\\)\\|U\\(?:\\(?:krainia\\|nknow\\)n\\)\\|Vietnamese\\)\\)?\\)\\)\\)\\|T\\(?:R\\(?:IANGLE\\(?:S\\|_STRIP\\)\\|S\\)\\|a\\(?:gField\\|n\\)\\|e\\(?:rrain\\(?:Collider\\|Data\\|Lighting\\(?:\\.\\(?:Lightmap\\|Pixel\\|Vertex\\)\\)?\\)?\\|st\\(?:Connection\\(?:NAT\\)?\\|PlanesAABB\\)\\|x\\(?:Coord[23]?\\|t\\(?:A\\(?:lignment\\(?:\\.\\(?:Center\\|\\(?:Lef\\|Righ\\)t\\)\\)?\\|nchor\\(?:\\.\\(?:Lower\\(?:Center\\|\\(?:Lef\\|Righ\\)t\\)\\|Middle\\(?:Center\\|\\(?:Lef\\|Righ\\)t\\)\\|Upper\\(?:Center\\|\\(?:Lef\\|Righ\\)t\\)\\)\\)?\\|rea\\|sset\\)\\|Clipping\\(?:\\.\\(?:Clip\\|Overflow\\)\\)?\\|Field\\|Mesh\\|ure\\(?:2D\\|Format\\(?:\\.\\(?:A\\(?:RGB32\\|lpha8\\)\\|DXT[15]\\|PVRTC_RGB\\(?:A[24]\\|[24]\\)\\|RGB24\\)\\)?\\|Importer\\(?:Format\\(?:\\.\\(?:A\\(?:RGB\\(?:16\\|32\\)\\|lpha8\\|utomatic\\)\\|DXT[15]\\|PVRTC_RGB\\(?:A[24]\\|[24]\\)\\|RGB\\(?:16\\|24\\)\\)\\)?\\|GenerateCubemap\\(?:\\.\\(?:Cylindrical\\|N\\(?:iceSpheremap\\|one\\)\\|S\\(?:\\(?:impleS\\)?pheremap\\)\\)\\)?\\|MipFilter\\(?:\\.\\(?:\\(?:Box\\|Kaiser\\)Filter\\)\\)?\\|N\\(?:POTScale\\(?:\\.\\(?:None\\|To\\(?:Larger\\|Nearest\\|Smaller\\)\\)\\)?\\|ormalFilter\\(?:\\.S\\(?:obel\\|tandard\\)\\)?\\)\\)?\\|WrapMode\\(?:\\.\\(?:Clamp\\|Repeat\\)\\)?\\)?\\)\\)\\)\\|hreadPriority\\(?:\\.\\(?:BelowNormal\\|High\\|Low\\|Normal\\)\\)?\\|ime\\|o\\(?:AngleAxis\\|String\\|ggle\\|olbar\\)\\|r\\(?:a\\(?:ilRenderer\\|ns\\(?:form\\(?:Direction\\|Point\\)?\\|late\\)\\)\\|ueTypeFontImporter\\)\\)\\|U\\(?:n\\(?:EscapeURL\\|do\\|focusWindow\\|lo\\(?:ad\\(?:UnusedAssets\\)?\\|ckReloadAssemblies\\)\\|\\(?:registerHos\\|shif\\)t\\)\\|\\(?:pdat\\|s\\)e\\)\\|V\\(?:alidateMoveAsset\\|e\\(?:ctor\\(?:[234]Field\\|[234]\\)\\|rt\\(?:ex3?\\|icalS\\(?:\\(?:crollba\\|lide\\)r\\)\\)\\)\\|iewport\\(?:PointToRay\\|To\\(?:\\(?:Screen\\|World\\)Point\\)\\)?\\)\\|W\\(?:WW\\(?:Form\\)?\\|a\\(?:itFor\\(?:EndOfFrame\\|FixedUpdate\\|Seconds\\)\\|keUp\\)\\|heel\\(?:Collider\\|FrictionCurve
'("\\<\\(c\\(?:atch\\|lass\\)\\|else\\|f\\(?:or\\(?:each\\)?\\|unction\\)\\|i\\(?:f\\|mport\\)\\|new\\|p\\(?:rivate\\|ublic\\)\\|return\\|s\\(?:tatic\\|witch\\)\\|try\\|var\\|while\\)\\>" . font-lock-keyword-face))
"Minimal highlighting expressions for unityjs mode")
(defconst unityjs-font-lock-keywords-2
(append unityjs-font-lock-keywords-1
(list
'("\\<\\(Date\\|Number\\|Array\\|Object\\|Regex\\|b\\(oolean\\|yte\\)\\|char\\|double\\|float\\|int\\|long\\|s\\(byte\\|hort\\|tring\\)\\|u\\(long\\|\\(ni\\|shor\\)t\\)\\|void\\)\\>" . font-lock-type-face)
'("\\<\\(true\\|false\\|null\\)\\>" . font-lock-reference-face)))
"Additional Keywords to highlight in UnityJS mode")
(defvar unityjs-font-lock-keywords unityjs-font-lock-keywords-2
"Default highlighting expressions for UnityJS mode")
;;;;;;;;;;;;;;;;;
;; INDENTATION ;;
;;;;;;;;;;;;;;;;;
(defcustom js-indent-level 8
"Number of spaces for each indentation step in `js-mode'."
:type 'integer
:group 'js)
(defcustom js-expr-indent-offset 0
"Number of additional spaces used for indentation of continued expressions.
The value must be no less than minus `js-indent-level'."
:type 'integer
:group 'js)
(defun js--regexp-opt-symbol (list)
"Like `regexp-opt', but surround the result with `\\\\_<' and `\\\\_>'."
(concat "\\_<" (regexp-opt list t) "\\_>"))
(defcustom js-comment-lineup-func #'c-lineup-C-comments
"Lineup function for `cc-mode-style', for C comments in `js-mode'."
:type 'function
:group 'js)
(defun js--re-search-backward-inner (regexp &optional bound count)
"Auxiliary function for `js--re-search-backward'."
(let ((parse)
str-terminator
(orig-macro-start
(save-excursion
(and (js--beginning-of-macro)
(point)))))
(while (> count 0)
(re-search-backward regexp bound)
(when (and (> (point) (point-min))
(save-excursion (backward-char) (looking-at "/[/*]")))
(forward-char))
(setq parse (syntax-ppss))
(cond ((setq str-terminator (nth 3 parse))
(when (eq str-terminator t)
(setq str-terminator ?/))
(re-search-backward
(concat "\\([^\\]\\|^\\)" (string str-terminator))
(save-excursion (beginning-of-line) (point)) t))
((nth 7 parse)
(goto-char (nth 8 parse)))
((or (nth 4 parse)
(and (eq (char-before) ?/) (eq (char-after) ?*)))
(re-search-backward "/\\*"))
((and (not (and orig-macro-start
(>= (point) orig-macro-start)))
(js--beginning-of-macro)))
(t
(setq count (1- count))))))
(point))
(defconst js--opt-cpp-start "^\\s-*#\\s-*\\([[:alnum:]]+\\)"
"Regexp matching the prefix of a cpp directive.
This includes the directive name, or nil in languages without
preprocessor support. The first submatch surrounds the directive
name.")
(defun js--beginning-of-macro (&optional lim)
(let ((here (point)))
(save-restriction
(if lim (narrow-to-region lim (point-max)))
(beginning-of-line)
(while (eq (char-before (1- (point))) ?\\)
(forward-line -1))
(back-to-indentation)
(if (and (<= (point) here)
(looking-at js--opt-cpp-start))
t
(goto-char here)
nil))))
(defun js--re-search-backward (regexp &optional bound noerror count)
"Search backward, ignoring strings, preprocessor macros, and comments.
This function invokes `re-search-backward' but treats the buffer
as if strings, preprocessor macros, and comments have been
removed.
If invoked while inside a macro, treat the macro as normal text."
(let ((saved-point (point))
(search-expr
(cond ((null count)
'(js--re-search-backward-inner regexp bound 1))
((< count 0)
'(js--re-search-forward-inner regexp bound (- count)))
((> count 0)
'(js--re-search-backward-inner regexp bound count)))))
(condition-case err
(eval search-expr)
(search-failed
(goto-char saved-point)
(unless noerror
(error (error-message-string err)))))))
(defconst js--possibly-braceless-keyword-re
(js--regexp-opt-symbol
'("catch" "do" "else" "finally" "for" "if" "try" "while" "with"
"each"))
"Regexp matching keywords optionally followed by an opening brace.")
(defconst js--indent-operator-re
(concat "[-+*/%<>=&^|?:.]\\([^-+*/]\\|$\\)\\|"
(js--regexp-opt-symbol '("in" "instanceof")))
"Regexp matching operators that affect indentation of continued expressions.")
(defun js--looking-at-operator-p ()
"Return non-nil if point is on a JavaScript operator, other than a comma."
(save-match-data
(and (looking-at js--indent-operator-re)
(or (not (looking-at ":"))
(save-excursion
(and (js--re-search-backward "[?:{]\\|\\_<case\\_>" nil t)
(looking-at "?")))))))
(defun js--continued-expression-p ()
"Return non-nil if the current line continues an expression."
(save-excursion
(back-to-indentation)
(or (js--looking-at-operator-p)
(and (js--re-search-backward "\n" nil t)
(progn
(skip-chars-backward " \t")
(or (bobp) (backward-char))
(and (> (point) (point-min))
(save-excursion (backward-char) (not (looking-at "[/*]/")))
(js--looking-at-operator-p)
(and (progn (backward-char)
(not (looking-at "++\\|--\\|/[/*]"))))))))))
(defun js--end-of-do-while-loop-p ()
"Return non-nil if point is on the \"while\" of a do-while statement.
Otherwise, return nil. A braceless do-while statement spanning
several lines requires that the start of the loop is indented to
the same column as the current line."
(interactive)
(save-excursion
(save-match-data
(when (looking-at "\\s-*\\_<while\\_>")
(if (save-excursion
(skip-chars-backward "[ \t\n]*}")
(looking-at "[ \t\n]*}"))
(save-excursion
(backward-list) (forward-symbol -1) (looking-at "\\_<do\\_>"))
(js--re-search-backward "\\_<do\\_>" (point-at-bol) t)
(or (looking-at "\\_<do\\_>")
(let ((saved-indent (current-indentation)))
(while (and (js--re-search-backward "^\\s-*\\_<" nil t)
(/= (current-indentation) saved-indent)))
(and (looking-at "\\s-*\\_<do\\_>")
(not (js--re-search-forward
"\\_<while\\_>" (point-at-eol) t))
(= (current-indentation) saved-indent)))))))))
(defun js--ctrl-statement-indentation ()
"Helper function for `js--proper-indentation'.
Return the proper indentation of the current line if it starts
the body of a control statement without braces; otherwise, return
nil."
(save-excursion
(back-to-indentation)
(when (save-excursion
(and (not (eq (point-at-bol) (point-min)))
(not (looking-at "[{]"))
(progn
(js--re-search-backward "[[:graph:]]" nil t)
(or (eobp) (forward-char))
(when (= (char-before) ?\)) (backward-list))
(skip-syntax-backward " ")
(skip-syntax-backward "w_")
(looking-at js--possibly-braceless-keyword-re))
(not (js--end-of-do-while-loop-p))))
(save-excursion
(goto-char (match-beginning 0))
(+ (current-indentation) js-indent-level)))))
(defun js--get-c-offset (symbol anchor)
(let ((c-offsets-alist
(list (cons 'c js-comment-lineup-func))))
(c-get-syntactic-indentation (list (cons symbol anchor)))))
(defun js--proper-indentation (parse-status)
"Return the proper indentation for the current line."
(save-excursion
(back-to-indentation)
(cond ((nth 4 parse-status)
(js--get-c-offset 'c (nth 8 parse-status)))
((nth 8 parse-status) 0) ; inside string
((js--ctrl-statement-indentation))
((eq (char-after) ?#) 0)
((save-excursion (js--beginning-of-macro)) 4)
((nth 1 parse-status)
(let ((same-indent-p (looking-at
"[]})]\\|\\_<case\\_>\\|\\_<default\\_>"))
(continued-expr-p (js--continued-expression-p)))
(goto-char (nth 1 parse-status))
(if (looking-at "[({[]\\s-*\\(/[/*]\\|$\\)")
(progn
(skip-syntax-backward " ")
(when (eq (char-before) ?\)) (backward-list))
(back-to-indentation)
(cond (same-indent-p
(current-column))
(continued-expr-p
(+ (current-column) (* 2 js-indent-level)
js-expr-indent-offset))
(t
(+ (current-column) js-indent-level))))
(unless same-indent-p
(forward-char)
(skip-chars-forward " \t"))
(current-column))))
((js--continued-expression-p)
(+ js-indent-level js-expr-indent-offset))
(t 0))))
(defun js-indent-line ()
"Indent the current line as JavaScript."
(interactive)
(save-restriction
(widen)
(let* ((parse-status
(save-excursion (syntax-ppss (point-at-bol))))
(offset (- (current-column) (current-indentation))))
(indent-line-to (js--proper-indentation parse-status))
(when (> offset 0) (forward-char offset)))))
;;;;;;;;;;;;;;;;;;;;;;;
;; INDENTATION ENDS ;;
;;;;;;;;;;;;;;;;;;;;;;;
;; Syntax table
(defvar unityjs-mode-syntax-table
(let ((unityjs-mode-syntax-table (make-syntax-table)))
(modify-syntax-entry ?_ "w" unityjs-mode-syntax-table)
(modify-syntax-entry ?/ ". 124b" unityjs-mode-syntax-table)
(modify-syntax-entry ?* ". 23" unityjs-mode-syntax-table)
(modify-syntax-entry ?\n "> b" unityjs-mode-syntax-table)
unityjs-mode-syntax-table)
"Syntax table for unityjs-mode")
(defun unityjs-mode ()
"Major mode for editing Unity Javascript files"
(interactive)
(kill-all-local-variables)
(set-syntax-table unityjs-mode-syntax-table)
(use-local-map unityjs-mode-map)
(set (make-local-variable 'font-lock-defaults) '(unityjs-font-lock-keywords))
(set (make-local-variable 'indent-line-function) 'js-indent-line)
(setq major-mode 'unityjs-mode)
(setq mode-name "unityjs-mode")
(run-hooks 'unityjs-mode-hook))
(provide 'unityjs-mode)