local packages not in git repos or package managers

This commit is contained in:
Janis 2024-10-17 20:25:33 +02:00
parent c26662171d
commit 607bb9b3b1
3 changed files with 1229 additions and 0 deletions

451
local-lisp/glsl-mode.el Normal file
View file

@ -0,0 +1,451 @@
;;; glsl-mode.el --- major mode for Open GLSL shader files
;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
;; Copyright (C) 2011, 2014, 2019 Jim Hourihan
;;
;; Authors: Xavier.Decoret@imag.fr,
;; Jim Hourihan <jimhourihan ~at~ gmail.com> (updated for 4.6, etc)
;; Keywords: languages OpenGL GPU SPIR-V Vulkan
;; Version: 2.4
;; X-URL: https://github.com/jimhourihan/glsl-mode
;;
;; Original X-URL http://artis.inrialpes.fr/~Xavier.Decoret/resources/glsl-mode/
;; 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 3, 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.
;; For a full copy of the GNU General Public License
;; see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Major mode for editing OpenGLSL grammar files, usually files ending with
;; `.vert', `.frag', `.glsl', `.geom'. Is is based on c-mode plus some
;; features and pre-specified fontifications.
;;
;; Modifications from the 1.0 version of glsl-mode (jimhourihan):
;; * Removed original optimized regexps for font-lock-keywords and
;; replaced with keyword lists for easier maintenance
;; * Added customization group and faces
;; * Preprocessor faces
;; * Updated to GLSL 4.6
;; * Separate deprecated symbols
;; * Made _ part of a word
;; * man page lookup at opengl.org
;; This package provides the following features:
;; * Syntax coloring (via font-lock) for grammar symbols and
;; builtin functions and variables for up to GLSL version 4.6
;; * Indentation for the current line (TAB) and selected region (C-M-\).
;; * Switching between file.vert and file.frag
;; with S-lefttab (via ff-find-other-file)
;; * interactive function glsl-find-man-page prompts for glsl built
;; in function, formats opengl.org url and passes to browse-url
;;; Installation:
;; This file requires Emacs-20.3 or higher and package cc-mode.
;; If glsl-mode is not part of your distribution, put this file into your
;; load-path and the following into your ~/.emacs:
;; (autoload 'glsl-mode "glsl-mode" nil t)
;; (add-to-list 'auto-mode-alist '("\\.glsl\\'" . glsl-mode))
;; (add-to-list 'auto-mode-alist '("\\.vert\\'" . glsl-mode))
;; (add-to-list 'auto-mode-alist '("\\.frag\\'" . glsl-mode))
;; (add-to-list 'auto-mode-alist '("\\.geom\\'" . glsl-mode))
;; Reference:
;; https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf
;;; Code:
(provide 'glsl-mode)
(eval-when-compile ; required and optional libraries
(require 'cc-mode)
(require 'find-file))
(require 'align)
(defgroup glsl nil
"OpenGL Shading Language Major Mode"
:group 'languages)
(defconst glsl-language-version "4.6"
"GLSL language version number.")
(defconst gl-version "4.6"
"OpenGL major mode version number.")
(defvar glsl-mode-menu nil "Menu for GLSL mode")
(defvar glsl-mode-hook nil "GLSL mode hook")
(defvar glsl-type-face 'glsl-type-face)
(defface glsl-type-face
'((t (:inherit font-lock-type-face))) "glsl: type face"
:group 'glsl)
(defvar glsl-builtin-face 'glsl-builtin-face)
(defface glsl-builtin-face
'((t (:inherit font-lock-builtin-face))) "glsl: builtin face"
:group 'glsl)
(defvar glsl-deprecated-builtin-face 'glsl-deprecated-builtin-face)
(defface glsl-deprecated-builtin-face
'((t (:inherit font-lock-warning-face))) "glsl: deprecated builtin face"
:group 'glsl)
(defvar glsl-qualifier-face 'glsl-qualifier-face)
(defface glsl-qualifier-face
'((t (:inherit font-lock-keyword-face))) "glsl: qualifier face"
:group 'glsl)
(defvar glsl-keyword-face 'glsl-keyword-face)
(defface glsl-keyword-face
'((t (:inherit font-lock-keyword-face))) "glsl: keyword face"
:group 'glsl)
(defvar glsl-deprecated-keyword-face 'glsl-deprecated-keyword-face)
(defface glsl-deprecated-keyword-face
'((t (:inherit font-lock-warning-face))) "glsl: deprecated keyword face"
:group 'glsl)
(defvar glsl-variable-name-face 'glsl-variable-name-face)
(defface glsl-variable-name-face
'((t (:inherit font-lock-variable-name-face))) "glsl: variable face"
:group 'glsl)
(defvar glsl-deprecated-variable-name-face 'glsl-deprecated-variable-name-face)
(defface glsl-deprecated-variable-name-face
'((t (:inherit font-lock-warning-face))) "glsl: deprecated variable face"
:group 'glsl)
(defvar glsl-reserved-keyword-face 'glsl-reserved-keyword-face)
(defface glsl-reserved-keyword-face
'((t (:inherit glsl-keyword-face))) "glsl: reserved keyword face"
:group 'glsl)
(defvar glsl-preprocessor-face 'glsl-preprocessor-face)
(defface glsl-preprocessor-face
'((t (:inherit font-lock-preprocessor-face))) "glsl: preprocessor face"
:group 'glsl)
(defcustom glsl-additional-types nil
"List of additional keywords to be considered types. These are
added to the `glsl-type-list' and are fontified using the
`glsl-type-face'. Examples of existing types include \"float\", \"vec4\",
and \"int\"."
:type '(repeat (string :tag "Type Name"))
:group 'glsl)
(defcustom glsl-additional-qualifiers nil
"List of additional keywords to be considered qualifiers. These
are added to the `glsl-qualifier-list' and are fontified using
the `glsl-qualifier-face'. Examples of existing qualifiers
include \"const\", \"in\", and \"out\"."
:type '(repeat (string :tag "Qualifier Name"))
:group 'glsl)
(defcustom glsl-additional-keywords nil
"List of additional GLSL keywords. These are added to the
`glsl-keyword-list' and are fontified using the
`glsl-keyword-face'. Example existing keywords include \"while\",
\"if\", and \"return\"."
:type '(repeat (string :tag "Keyword"))
:group 'glsl)
(defcustom glsl-additional-built-ins nil
"List of additional functions to be considered built-in. These
are added to the `glsl-builtin-list' and are fontified using the
`glsl-builtin-face'."
:type '(repeat (string :tag "Keyword"))
:group 'glsl)
(defvar glsl-mode-hook nil)
(defvar glsl-mode-map
(let ((glsl-mode-map (make-sparse-keymap)))
(define-key glsl-mode-map [S-iso-lefttab] 'ff-find-other-file)
glsl-mode-map)
"Keymap for GLSL major mode.")
(defcustom glsl-browse-url-function 'browse-url
"Function used to display GLSL man pages. E.g. browse-url, eww, w3m, etc"
:type 'function
:group 'glsl)
(defcustom glsl-man-pages-base-url "http://www.opengl.org/sdk/docs/man/html/"
"Location of GL man pages."
:type 'string
:group 'glsl)
;;;###autoload
(progn
(add-to-list 'auto-mode-alist '("\\.vert\\'" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.frag\\'" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.geom\\'" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.glsl\\'" . glsl-mode)))
(eval-and-compile
;; These vars are useful for completion so keep them around after
;; compile as well. The goal here is to have the byte compiled code
;; have optimized regexps so its not done at eval time.
(defvar glsl-type-list
'("float" "double" "int" "void" "bool" "true" "false" "mat2" "mat3"
"mat4" "dmat2" "dmat3" "dmat4" "mat2x2" "mat2x3" "mat2x4" "dmat2x2"
"dmat2x3" "dmat2x4" "mat3x2" "mat3x3" "mat3x4" "dmat3x2" "dmat3x3"
"dmat3x4" "mat4x2" "mat4x3" "mat4x4" "dmat4x2" "dmat4x3" "dmat4x4" "vec2"
"vec3" "vec4" "ivec2" "ivec3" "ivec4" "bvec2" "bvec3" "bvec4" "dvec2"
"dvec3" "dvec4" "uint" "uvec2" "uvec3" "uvec4" "atomic_uint"
"sampler1D" "sampler2D" "sampler3D" "samplerCube" "sampler1DShadow"
"sampler2DShadow" "samplerCubeShadow" "sampler1DArray" "sampler2DArray"
"sampler1DArrayShadow" "sampler2DArrayShadow" "isampler1D" "isampler2D"
"isampler3D" "isamplerCube" "isampler1DArray" "isampler2DArray"
"usampler1D" "usampler2D" "usampler3D" "usamplerCube" "usampler1DArray"
"usampler2DArray" "sampler2DRect" "sampler2DRectShadow" "isampler2DRect"
"usampler2DRect" "samplerBuffer" "isamplerBuffer" "usamplerBuffer"
"sampler2DMS" "isampler2DMS" "usampler2DMS" "sampler2DMSArray"
"isampler2DMSArray" "usampler2DMSArray" "samplerCubeArray"
"samplerCubeArrayShadow" "isamplerCubeArray" "usamplerCubeArray"
"image1D" "iimage1D" "uimage1D" "image2D" "iimage2D" "uimage2D" "image3D"
"iimage3D" "uimage3D" "image2DRect" "iimage2DRect" "uimage2DRect"
"imageCube" "iimageCube" "uimageCube" "imageBuffer" "iimageBuffer"
"uimageBuffer" "image1DArray" "iimage1DArray" "uimage1DArray"
"image2DArray" "iimage2DArray" "uimage2DArray" "imageCubeArray"
"iimageCubeArray" "uimageCubeArray" "image2DMS" "iimage2DMS" "uimage2DMS"
"image2DMSArray" "iimage2DMSArray" "uimage2DMSArray"))
(defvar glsl-qualifier-list
'("attribute" "const" "uniform" "varying" "buffer" "shared" "coherent"
"volatile" "restrict" "readonly" "writeonly" "layout" "centroid" "flat"
"smooth" "noperspective" "patch" "sample" "in" "out" "inout"
"invariant" "lowp" "mediump" "highp"))
(defvar glsl-keyword-list
'("break" "continue" "do" "for" "while" "if" "else" "subroutine"
"discard" "return" "precision" "struct" "switch" "default" "case"))
(defvar glsl-reserved-list
'("input" "output" "asm" "class" "union" "enum" "typedef" "template" "this"
"packed" "resource" "goto" "inline" "noinline"
"common" "partition" "active" "long" "short" "half" "fixed" "unsigned" "superp"
"public" "static" "extern" "external" "interface"
"hvec2" "hvec3" "hvec4" "fvec2" "fvec3" "fvec4"
"filter" "sizeof" "cast" "namespace" "using"
"sampler3DRect"))
(defvar glsl-deprecated-qualifier-list
'("varying" "attribute")) ; centroid is deprecated when used with varying
(defvar glsl-builtin-list
'("abs" "acos" "acosh" "all" "any" "anyInvocation" "allInvocations"
"allInvocationsEqual" "asin" "asinh" "atan" "atanh"
"atomicAdd" "atomicMin" "atomicMax" "atomicAnd" "atomicOr"
"atomicXor" "atomicExchange" "atomicCompSwap"
"atomicCounter" "atomicCounterDecrement" "atomicCounterIncrement"
"atomicCounterAdd" "atomicCounterSubtract" "atomicCounterMin"
"atomicCounterMax" "atomicCounterAnd" "atomicCounterOr"
"atomicCounterXor" "atomicCounterExchange" "atomicCounterCompSwap"
"barrier" "bitCount" "bitfieldExtract" "bitfieldInsert" "bitfieldReverse"
"ceil" "clamp" "cos" "cosh" "cross" "degrees" "determinant" "dFdx" "dFdy"
"dFdyFine" "dFdxFine" "dFdyCoarse" "dFdxCoarse" "distance" "dot"
"fwidthFine" "fwidthCoarse"
"EmitStreamVertex" "EmitStreamPrimitive" "EmitVertex" "EndPrimitive"
"EndStreamPrimitive" "equal" "exp" "exp2" "faceforward" "findLSB"
"findMSB" "floatBitsToInt" "floatBitsToUint" "floor" "fma" "fract"
"frexp" "fwidth" "greaterThan" "greaterThanEqual" "groupMemoryBarrier"
"imageAtomicAdd" "imageAtomicAnd" "imageAtomicCompSwap" "imageAtomicExchange"
"imageAtomicMax" "imageAtomicMin" "imageAtomicOr" "imageAtomicXor"
"imageLoad" "imageSize" "imageStore" "imulExtended" "intBitsToFloat"
"imageSamples" "interpolateAtCentroid" "interpolateAtOffset" "interpolateAtSample"
"inverse" "inversesqrt" "isinf" "isnan" "ldexp" "length" "lessThan"
"lessThanEqual" "log" "log2" "matrixCompMult" "max" "memoryBarrier"
"memoryBarrierAtomicCounter" "memoryBarrierBuffer"
"memoryBarrierShared" "memoryBarrierImage" "memoryBarrier"
"min" "mix" "mod" "modf" "normalize" "not" "notEqual" "outerProduct"
"packDouble2x32" "packHalf2x16" "packSnorm2x16" "packSnorm4x8"
"packUnorm2x16" "packUnorm4x8" "pow" "radians" "reflect" "refract"
"round" "roundEven" "sign" "sin" "sinh" "smoothstep" "sqrt" "step" "tan"
"tanh" "texelFetch" "texelFetchOffset" "texture" "textureGather"
"textureGatherOffset" "textureGatherOffsets" "textureGrad" "textureSamples"
"textureGradOffset" "textureLod" "textureLodOffset" "textureOffset"
"textureProj" "textureProjGrad" "textureProjGradOffset" "textureProjLod"
"textureProjLodOffset" "textureProjOffset" "textureQueryLevels" "textureQueryLod"
"textureSize" "transpose" "trunc" "uaddCarry" "uintBitsToFloat"
"umulExtended" "unpackDouble2x32" "unpackHalf2x16" "unpackSnorm2x16"
"unpackSnorm4x8" "unpackUnorm2x16" "unpackUnorm4x8" "usubBorrow"))
(defvar glsl-deprecated-builtin-list
'("noise1" "noise2" "noise3" "noise4"
"texture1D" "texture1DProj" "texture1DLod" "texture1DProjLod"
"texture2D" "texture2DProj" "texture2DLod" "texture2DProjLod"
"texture2DRect" "texture2DRectProj"
"texture3D" "texture3DProj" "texture3DLod" "texture3DProjLod"
"shadow1D" "shadow1DProj" "shadow1DLod" "shadow1DProjLod"
"shadow2D" "shadow2DProj" "shadow2DLod" "shadow2DProjLod"
"textureCube" "textureCubeLod"))
(defvar glsl-deprecated-variables-list
'("gl_FragColor" "gl_FragData" "gl_MaxVarying" "gl_MaxVaryingFloats"
"gl_MaxVaryingComponents"))
(defvar glsl-preprocessor-directive-list
'("define" "undef" "if" "ifdef" "ifndef" "else" "elif" "endif"
"error" "pragma" "extension" "version" "line"))
(defvar glsl-preprocessor-expr-list
'("defined" "##"))
(defvar glsl-preprocessor-builtin-list
'("__LINE__" "__FILE__" "__VERSION__"))
) ; eval-and-compile
(eval-and-compile
(defun glsl-ppre (re)
(format "\\<\\(%s\\)\\>" (regexp-opt re))))
(defvar glsl-font-lock-keywords-1
(append
(list
(cons (eval-when-compile
(format "^[ \t]*#[ \t]*\\<\\(%s\\)\\>"
(regexp-opt glsl-preprocessor-directive-list)))
glsl-preprocessor-face)
(cons (eval-when-compile
(glsl-ppre glsl-type-list))
glsl-type-face)
(cons (eval-when-compile
(glsl-ppre glsl-deprecated-qualifier-list))
glsl-deprecated-keyword-face)
(cons (eval-when-compile
(glsl-ppre glsl-reserved-list))
glsl-reserved-keyword-face)
(cons (eval-when-compile
(glsl-ppre glsl-qualifier-list))
glsl-qualifier-face)
(cons (eval-when-compile
(glsl-ppre glsl-keyword-list))
glsl-keyword-face)
(cons (eval-when-compile
(glsl-ppre glsl-preprocessor-builtin-list))
glsl-keyword-face)
(cons (eval-when-compile
(glsl-ppre glsl-deprecated-builtin-list))
glsl-deprecated-builtin-face)
(cons (eval-when-compile
(glsl-ppre glsl-builtin-list))
glsl-builtin-face)
(cons (eval-when-compile
(glsl-ppre glsl-deprecated-variables-list))
glsl-deprecated-variable-name-face)
(cons "gl_[A-Z][A-Za-z_]+" glsl-variable-name-face)
)
(when glsl-additional-types
(list
(cons (glsl-ppre glsl-additional-types) glsl-type-face)))
(when glsl-additional-keywords
(list
(cons (glsl-ppre glsl-additional-keywords) glsl-keyword-face)))
(when glsl-additional-qualifiers
(list
(cons (glsl-ppre glsl-additional-qualifiers) glsl-qualifier-face)))
(when glsl-additional-built-ins
(list
(cons (glsl-ppre glsl-additional-built-ins) glsl-builtin-face)))
)
"Highlighting expressions for GLSL mode.")
(defvar glsl-font-lock-keywords glsl-font-lock-keywords-1
"Default highlighting expressions for GLSL mode.")
(defvar glsl-mode-syntax-table
(let ((glsl-mode-syntax-table (make-syntax-table)))
(modify-syntax-entry ?/ ". 124b" glsl-mode-syntax-table)
(modify-syntax-entry ?* ". 23" glsl-mode-syntax-table)
(modify-syntax-entry ?\n "> b" glsl-mode-syntax-table)
(modify-syntax-entry ?_ "w" glsl-mode-syntax-table)
glsl-mode-syntax-table)
"Syntax table for glsl-mode.")
(defvar glsl-other-file-alist
'(("\\.frag$" (".vert"))
("\\.vert$" (".frag"))
)
"Alist of extensions to find given the current file's extension.")
(defun glsl-man-completion-list ()
"Return list of all GLSL keywords."
(append glsl-builtin-list glsl-deprecated-builtin-list))
(defun glsl-find-man-page (thing)
"Collects and displays manual entry for GLSL built-in function THING."
(interactive
(let ((word (current-word nil t)))
(list
(completing-read
(concat "OpenGL.org GLSL man page: (" word "): ")
(glsl-man-completion-list)
nil nil nil nil word))))
(save-excursion
(apply glsl-browse-url-function
(list (concat glsl-man-pages-base-url thing ".xhtml")))))
(easy-menu-define glsl-menu glsl-mode-map
"GLSL Menu"
`("GLSL"
["Comment Out Region" comment-region
(c-fn-region-is-active-p)]
["Uncomment Region" (comment-region (region-beginning)
(region-end) '(4))
(c-fn-region-is-active-p)]
["Indent Expression" c-indent-exp
(memq (char-after) '(?\( ?\[ ?\{))]
["Indent Line or Region" c-indent-line-or-region t]
["Fill Comment Paragraph" c-fill-paragraph t]
"----"
["Backward Statement" c-beginning-of-statement t]
["Forward Statement" c-end-of-statement t]
"----"
["Up Conditional" c-up-conditional t]
["Backward Conditional" c-backward-conditional t]
["Forward Conditional" c-forward-conditional t]
"----"
["Backslashify" c-backslash-region (c-fn-region-is-active-p)]
"----"
["Find GLSL Man Page" glsl-find-man-page t]
))
;;;###autoload
(define-derived-mode glsl-mode prog-mode "GLSL"
"Major mode for editing GLSL shader files."
(c-initialize-cc-mode t)
(setq abbrev-mode t)
(c-init-language-vars-for 'c-mode)
(c-common-init 'c-mode)
(cc-imenu-init cc-imenu-c++-generic-expression)
(set (make-local-variable 'font-lock-defaults) '(glsl-font-lock-keywords))
(set (make-local-variable 'ff-other-file-alist) 'glsl-other-file-alist)
(set (make-local-variable 'comment-start) "// ")
(set (make-local-variable 'comment-end) "")
(set (make-local-variable 'comment-padding) "")
(easy-menu-add glsl-menu)
(add-to-list 'align-c++-modes 'glsl-mode)
(c-run-mode-hooks 'c-mode-common-hook)
(run-mode-hooks 'glsl-mode-hook)
:after-hook (progn (c-make-noise-macro-regexps)
(c-make-macro-with-semi-re)
(c-update-modeline))
)
;;; glsl-mode.el ends here

581
local-lisp/hlsl-mode.el Normal file
View file

@ -0,0 +1,581 @@
;;; hlsl-mode.el --- Major mode for HLSL shader files -*- lexical-binding: t; -*-
;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
;; Copyright (C) 2011, 2014, 2019 Jim Hourihan
;; Copyright (C) 2022 Jcaw
;;
;; Authors: Xavier.Decoret@imag.fr,
;; Jim Hourihan <jimhourihan ~at~ gmail.com>
;; GitHub user "jcaw"
;; Keywords: languages HLSL GPU shaders
;; Version: 1.1.3
;; URL: https://github.com/jcaw/hlsl-mode
;; Package-Requires: ((emacs "24.4"))
;;
;; Original URL http://artis.inrialpes.fr/~Xavier.Decoret/resources/glsl-mode/
;; 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 3, 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.
;; For a full copy of the GNU General Public License
;; see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Major mode for editing OpenHLSL grammar files, usually files ending with
;; `.fx[hc]', `.hlsl', `.shader', `.compute'. It is based on c-mode plus some
;; features and pre-specified fontifications.
;;
;; It is modified from `glsl-mode', maintained at the time of writing by Jim
;; Hourihan: https://github.com/jimhourihan/glsl-mode
;; This package provides the following features:
;; * Syntax coloring (via font-lock) for grammar symbols and
;; builtin functions and variables for HLSL (up to the version specified
;; by `hlsl-shader-model-version')
;; * Indentation for the current line (TAB) and selected region (C-M-\).
;;; Code:
(require 'cc-mode)
(eval-when-compile ; required and optional libraries
(require 'find-file)
(require 'subr-x))
(require 'align)
(defgroup hlsl nil
"Microsoft HLSL Major Mode."
:group 'languages)
(defconst hlsl-shader-model-version "6.0"
"Shader model version number.")
(defconst hlsl-direct3d-version "12"
"Direct3D language version number.")
(defvar hlsl-type-face 'hlsl-type-face)
(defface hlsl-type-face
'((t (:inherit font-lock-type-face))) "HLSL: type face."
:group 'hlsl)
(defvar hlsl-builtin-face 'hlsl-builtin-face)
(defface hlsl-builtin-face
'((t (:inherit font-lock-builtin-face))) "HLSL: builtin face."
:group 'hlsl)
(defvar hlsl-deprecated-builtin-face 'hlsl-deprecated-builtin-face)
(defface hlsl-deprecated-builtin-face
'((t (:inherit font-lock-warning-face))) "HLSL: deprecated builtin face."
:group 'hlsl)
(defvar hlsl-qualifier-face 'hlsl-qualifier-face)
(defface hlsl-qualifier-face
'((t (:inherit font-lock-keyword-face))) "HLSL: qualifier face."
:group 'hlsl)
(defvar hlsl-keyword-face 'hlsl-keyword-face)
(defface hlsl-keyword-face
'((t (:inherit font-lock-keyword-face))) "HLSL: keyword face."
:group 'hlsl)
(defvar hlsl-deprecated-keyword-face 'hlsl-deprecated-keyword-face)
(defface hlsl-deprecated-keyword-face
'((t (:inherit font-lock-warning-face))) "HLSL: deprecated keyword face."
:group 'hlsl)
(defvar hlsl-variable-name-face 'hlsl-variable-name-face)
(defface hlsl-variable-name-face
'((t (:inherit font-lock-variable-name-face))) "HLSL: variable face."
:group 'hlsl)
(defvar hlsl-deprecated-variable-name-face 'hlsl-deprecated-variable-name-face)
(defface hlsl-deprecated-variable-name-face
'((t (:inherit font-lock-warning-face))) "HLSL: deprecated variable face."
:group 'hlsl)
(defvar hlsl-reserved-keyword-face 'hlsl-reserved-keyword-face)
(defface hlsl-reserved-keyword-face
'((t (:inherit hlsl-keyword-face))) "HLSL: reserved keyword face."
:group 'hlsl)
(defvar hlsl-preprocessor-face 'hlsl-preprocessor-face)
(defface hlsl-preprocessor-face
'((t (:inherit font-lock-preprocessor-face))) "HLSL: preprocessor face."
:group 'hlsl)
(defcustom hlsl-additional-types nil
"List of additional keywords to be considered types.
These are added to the `hlsl-type-list' and are fontified using
the `hlsl-type-face'. Examples of existing types include
\"float\", \"float4\", and \"RWStructuredBuffer\"."
:type '(repeat (string :tag "Type Name"))
:group 'hlsl)
(defcustom hlsl-additional-qualifiers nil
"List of additional keywords to be considered qualifiers.
These are added to the `hlsl-qualifier-list' and are fontified
using the `hlsl-qualifier-face'. Examples of existing qualifiers
include \"const\", \"in\", and \"out\"."
:type '(repeat (string :tag "Qualifier Name"))
:group 'hlsl)
(defcustom hlsl-additional-keywords nil
"List of additional HLSL keywords.
These are added to the `hlsl-keyword-list' and are fontified
using the `hlsl-keyword-face'. Example existing keywords include
\"while\", \"if\", and \"return\"."
:type '(repeat (string :tag "Keyword"))
:group 'hlsl)
(defcustom hlsl-additional-built-ins nil
"List of additional functions to be considered built-in.
These are added to the `hlsl-builtin-list' and are fontified
using the `hlsl-builtin-face'."
:type '(repeat (string :tag "Keyword"))
:group 'hlsl)
(defvar hlsl-mode-map
(let ((hlsl-mode-map (make-sparse-keymap)))
(define-key hlsl-mode-map [S-iso-lefttab] 'ff-find-other-file)
hlsl-mode-map)
"Keymap for HLSL major mode.")
;; (defcustom hlsl-browse-url-function 'browse-url
;; "Function used to display HLSL man pages.
;; E.g. `browse-url', `eww', `w3m', etc."
;; :type 'function
;; :group 'hlsl)
;; (defcustom hlsl-man-pages-base-url "http://www.opengl.org/sdk/docs/man/html/"
;; "Location of GL man pages."
;; :type 'string
;; :group 'hlsl)
;;;###autoload
(progn
(add-to-list 'auto-mode-alist '("\\.fx\\'" . hlsl-mode))
(add-to-list 'auto-mode-alist '("\\.fxc\\'" . hlsl-mode))
(add-to-list 'auto-mode-alist '("\\.fxh\\'" . hlsl-mode))
(add-to-list 'auto-mode-alist '("\\.hlsl\\'" . hlsl-mode))
(add-to-list 'auto-mode-alist '("\\.cg\\'" . hlsl-mode))
;; Unity shader format
(add-to-list 'auto-mode-alist '("\\.shader\\'" . hlsl-mode))
;; Unity shader include suffix
(add-to-list 'auto-mode-alist '("\\.cginc\\'" . hlsl-mode))
;; Unity compute shaders are HLSL
(add-to-list 'auto-mode-alist '("\\.compute\\'" . hlsl-mode))
)
(eval-and-compile
(defun hlsl--mixed-case (strings)
"Get original `strings', plus lowercase and uppercase versions.
For example:
(hlsl--mixed-case '(\"TexCoord\" \"POSITION\"))
-> '(\"TexCoord\" \"TEXCOORD\" \"Texcoord\"
\"POSITION\" \"Position\")
Returns a flattened list of all the resultant strings (without
duplicates)."
(apply #'append (mapcar (lambda (s)
(if (= 0 (length s))
s
(delete-dups
(list s (upcase s)
(concat (upcase (substring s 0 1))
(downcase (substring s 1)))))))
strings)))
;; These vars are useful for completion so keep them around after compile as
;; well. The goal here is to have the byte compiled code have optimized
;; regexps so its not done at eval time.
(defvar hlsl-type-list
`(
;; TODO: Maybe make `void' a keyword?
"matrix" "void"
;; Numeric scalars, plus all the vector and matrix expressions for each. E.g:
;; float, float1, float1x2, uint2, bool3x4, etc.
,@(mapcar (lambda (type)
(concat type "\\([1234]?\\|\\([1234]x[1234]\\)?\\)"))
'("bool" "int" "uint" "float"
"min16float" "min10float" "min16int" "min12int" "min16uint"))
;; These numeric scalars don't expand to vectors/matrices
"half" "dword" "double"
;; Texture samplers
"sampler" "sampler1D" "sampler2D" "sampler3D" "samplerCUBE" "sampler_state"
"SamplerState" "SampleComparisonState"
;; Buffer-esque types
"AppendStructuredBuffer" "Buffer" "ByteAddressBuffer" "ConsumeStructuredBuffer"
"InputPatch" "OutputPatch" "RWBuffer" "RWByteAddressBuffer" "RWStructuredBuffer"
"RWTexture1D" "RWTexture1DArray" "RWTexture2D" "RWTexture2DArray" "RWTexture3D"
"StructuredBuffer" "Texture1D" "Texture1DArray" "Texture2D" "Texture2DArray"
"Texture2DMS" "Texture2DMSArray" "Texture3D" "TextureCube" "TextureCubeArray"
;; Rasterizer Order Views
"RasterizerOrderedBuffer" "RasterizerOrderedByteAddressBuffer" "RasterizerOrderedStructuredBuffer"
"RasterizerOrderedTexture1D" "RasterizerOrderedTexture1DArray" "RasterizerOrderedTexture2D"
"RasterizerOrderedTexture2DArray" "RasterizerOrderedTexture3D"
;; Misc
;;
;; TODO: Double check Object2 usage
"Object2"
;; Geometry shader stream outputs
"PointStream" "LineStream" "TriangleStream"))
(defvar hlsl-qualifier-list
'(
;; Misc
"snorm" "unorm" "in" "inline" "inout" "precise" "extern" "nointerpolation"
"precise" "shared" "groupshared" "static" "uniform" "volatile" "const"
"row_major" "column_major" "export" "linear" "centroid" "noperspective"
"sample" "globallycoherent" "out"
;; Geom shader primitives
"point" "line" "triangle" "lineadj" "triangledj"
"pixelfragment" "vertexfragment"))
(defvar hlsl-keyword-list
`(
;; Special types
"true" "false" "NULL" "null"
;; Misc
"compile_fragment" "class" "interface" "break" "continue" "do" "default"
"discard" "for" "while" "if" "else" "return" "struct" "switch" "case"
"register" "packoffset" "cbuffer" "tbuffer" "fxgroup" "pass"
"technique[1-9]?[1-9]?"
"SetVertexShader" "SetGeometryShader" "SetPixelSader"
;; Attributes
"maxvertexcount" "domain" "earlydepthstencil" "instance" "maxtessfactor"
"numthreads" "outputcontrolpoints" "outputtopology" "partitioning"
"patchconstantfunc"
;; domain types
;; TODO: move these into a dedicated domain matcher?
;; TODO: `point' and `line' at least are duplicated here and in qualifiers
;; TODO: Take another look at these, they should probably be handled differently
"tri" "quad" "isoline" "point" "line" "triangle_cw" "triangle_ccw"
"integer" "fractional_even" "fractional_odd" "pow2"
;; Branching attributes
"unroll" "loop" "fastopt" "allow_uav_condition" "branch" "flatten"
"forcecase" "call"
;; Shader profiles
;;
;; Shader Model 1
"vs_1_1"
;; Shader Model 2
"ps_2_0" "ps_2_x" "vs_2_0" "vs_2_x" "ps_4_0_level_9_0" "ps_4_0_level_9_1"
"ps_4_0_level_9_3" "vs_4_0_level_9_0" "vs_4_0_level_9_1" "vs_4_0_level_9_3"
"lib_4_0_level_9_1" "lib_4_0_level_9_"
;; Shader Model 3
"ps_3_0" "vs_3_0"
;; Shader Model 4
"cs_4_0" "gs_4_0" "ps_4_0" "vs_4_0" "cs_4_1" "gs_4_1" "ps_4_1" "vs_4_1"
"lib_4_0" "lib_4_"
;; Shader Model 5
"cs_5_0" "ds_5_0" "gs_5_0" "hs_5_0" "ps_5_0" "vs_5_0" "lib_5_"
;; Shader Model 6
"cs_6_0" "ds_6_0" "gs_6_0" "hs_6_0" "ps_6_0" "vs_6_0" "lib_6_"
;; FX Profiles
"fx_1_0" "fx_2_0" "fx_4_0" "fx_4_1" "fx_5_0"
;; Semantics
;;
;; All semantics are case-insensitive, so allow uppercase, lowercase and
;; capitalised versions. Other/weird mixtures of case will not be
;; highlighted for now, even though the HLSL spec allows them.
,@(hlsl--mixed-case
'("Binormal[0-9]?" "BlendIndices[0-9]?" "BlendWeight[0-9]?" "Color[0-9]?"
"Normal[0-9]?" "Position[0-9]?" "PositionT" "PSize[0-9]?" "Tangent[0-9]?"
"TexCoord[0-9]" "Fog" "TessFactor[0-9]?" "VFace" "VPos" "Depth[0-9]?"
"SV_ClipDistance[0-9]?" "SV_CullDistance[0-9]?" "SV_Coverage" "SV_Depth"
"SV_DepthGreaterEqual" "SV_DepthLessEqual" "SV_DispatchThreadID"
"SV_DomainLocation" "SV_GroupID" "SV_GroupIndex" "SV_GroupThreadID"
"SV_GSInstanceID" "SV_InnerCoverage" "SV_InsideTessFactor" "SV_InstanceID"
"SV_IsFrontFace" "SV_OutputControlPointID" "SV_Position" "SV_PrimitiveID"
"SV_RenderTargetArrayIndex" "SV_SampleIndex" "SV_StencilRef" "SV_Target[0-7]"
"SV_TessFactor" "SV_VertexID" "SV_ViewportArrayIndex" "SV_ShadingRate"
"SV_Target"
;; Misc Semantics
"BezierPos" "WorldPos" "TanUCorner" "TanVCorner" "TanWeights" "Bitangent[0-9]?"))
;; Unity keywords
;;
;; TODO: Separate derived mode for Unity ".shader" files? They're not strictly HLSL.
"Shader" "Properties" "SubShader" "Tags" "Pass" "CGPROGRAM" "ENDCG"))
(defvar hlsl-reserved-list
'(
;; [2022/01/31] Just the reserved words found on:
;; https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-reserved-words
"auto" "case" "catch" "char" "class" "const_cast" "default" "delete" "dynamic_cast"
"enum" "explicit" "friend" "goto" "long" "mutable" "new" "operator" "private"
"protected" "public" "reinterpret_cast" "short" "signed" "sizeof" "static_cast"
"template" "this" "throw" "try" "typename" "union" "unsigned" "using" "virtual"))
(defvar hlsl-deprecated-qualifier-list
'())
(defvar hlsl-builtin-list
'(
;; This is the list of the builtins taken directly from the Direct3D 12 docs (Shader Model 6.0)
"abort" "abs" "acos" "all" "AllMemoryBarrier" "AllMemoryBarrierWithGroupSync"
"any" "asdouble" "asfloat" "asin" "asint" "asint" "asuint" "asuint" "atan" "atan2"
"ceil" "CheckAccessFullyMapped" "clamp" "clip" "cos" "cosh" "countbits" "cross"
"D3DCOLORtoUBYTE4" "ddx" "ddx_coarse" "ddx_fine" "ddy" "ddy_coarse" "ddy_fine"
"degrees" "determinant" "DeviceMemoryBarrier" "DeviceMemoryBarrierWithGroupSync"
"distance" "dot" "dst" "errorf" "EvaluateAttributeAtCentroid" "EvaluateAttributeAtSample"
"EvaluateAttributeSnapped" "exp" "exp2" "f16tof32" "f32tof16" "faceforward"
"firstbithigh" "firstbitlow" "floor" "fma" "fmod" "frac" "frexp" "fwidth"
"GetRenderTargetSampleCount" "GetRenderTargetSamplePosition" "GroupMemoryBarrier"
"GroupMemoryBarrierWithGroupSync" "InterlockedAdd" "InterlockedAnd"
"InterlockedCompareExchange" "InterlockedCompareStore" "InterlockedExchange"
"InterlockedMax" "InterlockedMin" "InterlockedOr" "InterlockedXor" "isfinite"
"isinf" "isnan" "ldexp" "length" "lerp" "lit" "log" "log10" "log2" "mad" "max"
"min" "modf" "msad4" "mul" "noise" "normalize" "pow" "printf"
"Process2DQuadTessFactorsAvg" "Process2DQuadTessFactorsMax" "Process2DQuadTessFactorsMin"
"ProcessIsolineTessFactors" "ProcessQuadTessFactorsAvg" "ProcessQuadTessFactorsMax"
"ProcessQuadTessFactorsMin" "ProcessTriTessFactorsAvg" "ProcessTriTessFactorsMax"
"ProcessTriTessFactorsMin" "radians" "rcp" "reflect" "refract" "reversebits"
"round" "rsqrt" "saturate" "sign" "sin" "sincos" "sinh" "smoothstep" "sqrt"
"step" "tan" "tanh" "tex1D" "tex1Dbias" "tex1Dgrad" "tex1Dlod" "tex1Dproj"
"tex2D" "tex2Dbias" "tex2Dgrad" "tex2Dlod" "tex2Dproj" "tex3D" "tex3Dbias"
"tex3Dgrad" "tex3Dlod" "tex3Dproj" "texCUBE" "texCUBEbias" "texCUBEgrad" "texCUBElod"
"texCUBEproj" "transpose" "trunc"
;; Geometry shader streams
"Append" "RestartStrip"
;; Textures/Buffers
"CalculateLevelOfDetail" "CalculateLevelOfDetailUnclamped" "Gather" "GetDimensions"
"GetSamplePosition" "Sample" "SampleBias" "SampleCmp" "SampleGrad" "SampleLevel"
"Operator\\[\\]" "Load[234]?" "Store[234]?"
"GatherRed" "GatherGreen" "GatherBlue" "GatherAlpha" "GatherCmp" "GatherCmpRed"
"GatherCmpGreen" "GatherCmpBlue" "GatherCmpAlpha"
"Sample" "SampleBias" "SampleCmp" "SampleCmpLevelZero" "SampleGrad" "SampleLevel"
;; Wave Intrinsics
"QuadReadAcrossDiagonal" "QuadReadLaneAt" "QuadReadAcrossX" "QuadReadAcrossY"
"WaveActiveAllEqual" "WaveActiveBitAnd" "WaveActiveBitOr" "WaveActiveBitXor"
"WaveActiveCountBits" "WaveActiveMax" "WaveActiveMin" "WaveActiveProduct"
"WaveActiveSum" "WaveActiveAllTrue" "WaveActiveAnyTrue" "WaveActiveBallot"
"WaveGetLaneCount" "WaveGetLaneIndex" "WaveIsFirstLane" "WavePrefixCountBits"
"WavePrefixProduct" "WavePrefixSum" "WaveReadLaneFirst" "WaveReadLaneAt"
;; Unsorted
"Consume" "DecrementCounter" "IncrementCounter"))
(defvar hlsl-deprecated-builtin-list
'())
(defvar hlsl-deprecated-variables-list
'())
(defvar hlsl-preprocessor-directive-list
'(
"define" "elif" "else" "endif" "error" "if" "ifdef" "ifndef" "include"
"line" "pragma" "undef"))
(defvar hlsl-preprocessor-expr-list
'(
;; Taken directly from glsl-mode - not audited yet
"defined" "##"))
(defvar hlsl-preprocessor-builtin-list
'(
;; Taken directly from glsl-mode - not audited yet
"__LINE__" "__FILE__" "__VERSION__"))
;; TODO: Highlighting for annotations <int something=27;>
) ; eval-and-compile
(eval-and-compile
(defun hlsl-ppre (re)
;; FIXME: This doesn't sanitise the inputs, so a bad member could corrupt the whole expression
(format "\\<\\(%s\\)\\>" (string-join re "\\|"))))
(defvar hlsl-font-lock-keywords-1
(append
(list
(cons (eval-when-compile
(format "^[ \t]*#[ \t]*\\<\\(%s\\)\\>"
(regexp-opt hlsl-preprocessor-directive-list)))
hlsl-preprocessor-face)
(cons (eval-when-compile
(hlsl-ppre hlsl-type-list))
hlsl-type-face)
(cons (eval-when-compile
(hlsl-ppre hlsl-deprecated-qualifier-list))
hlsl-deprecated-keyword-face)
(cons (eval-when-compile
(hlsl-ppre hlsl-reserved-list))
hlsl-reserved-keyword-face)
(cons (eval-when-compile
(hlsl-ppre hlsl-qualifier-list))
hlsl-qualifier-face)
(cons (eval-when-compile
(hlsl-ppre hlsl-keyword-list))
hlsl-keyword-face)
(cons (eval-when-compile
(hlsl-ppre hlsl-preprocessor-builtin-list))
hlsl-keyword-face)
(cons (eval-when-compile
(hlsl-ppre hlsl-deprecated-builtin-list))
hlsl-deprecated-builtin-face)
(cons (eval-when-compile
(hlsl-ppre hlsl-builtin-list))
hlsl-builtin-face)
(cons (eval-when-compile
(hlsl-ppre hlsl-deprecated-variables-list))
hlsl-deprecated-variable-name-face)
;; Swizzles are a special case. We want to highlight swizzles only when
;; they're after a dot, but we don't want to highlight the dot itself.
(list (eval-when-compile
;; TODO: Maybe these types of swizzles?
;; /\.\(_m[0-3]\{2}\)\{1,4\}/
;; /\.\(_[1-4]\{2}\)\{1,4\}/
"\\.\\_<\\([xyzw]\\{1,4\\}\\|[rgba]\\{1,4\\}\\)\\_>")
'(1 hlsl-builtin-face))
;; TODO: What to do about dedicated named variables?
;; (cons "unity_[A-Z0-9a-z_]+" hlsl-variable-name-face)
)
(when hlsl-additional-types
(list
(cons (hlsl-ppre hlsl-additional-types) hlsl-type-face)))
(when hlsl-additional-keywords
(list
(cons (hlsl-ppre hlsl-additional-keywords) hlsl-keyword-face)))
(when hlsl-additional-qualifiers
(list
(cons (hlsl-ppre hlsl-additional-qualifiers) hlsl-qualifier-face)))
(when hlsl-additional-built-ins
(list
(cons (hlsl-ppre hlsl-additional-built-ins) hlsl-builtin-face)))
)
"Highlighting expressions for HLSL mode.")
(defvar hlsl-font-lock-keywords hlsl-font-lock-keywords-1
"Default highlighting expressions for HLSL mode.")
(defvar hlsl-mode-syntax-table
(let ((hlsl-mode-syntax-table (make-syntax-table)))
(modify-syntax-entry ?/ ". 124b" hlsl-mode-syntax-table)
(modify-syntax-entry ?* ". 23" hlsl-mode-syntax-table)
(modify-syntax-entry ?\n "> b" hlsl-mode-syntax-table)
(modify-syntax-entry ?_ "w" hlsl-mode-syntax-table)
hlsl-mode-syntax-table)
"Syntax table for `hlsl-mode'.")
(defvar hlsl-other-file-alist
;; TODO: Add common pairings, e.g. vert & corresponding frag files, perhaps
;; also geom
'()
"Alist of extensions to find given the current file's extension.")
(defun hlsl-man-completion-list ()
"Return list of all HLSL keywords."
(append hlsl-builtin-list hlsl-deprecated-builtin-list))
;; TODO: Switch over to HLSL docs?
;; (defun hlsl-find-man-page (thing)
;; "Collects and displays manual entry for HLSL built-in function THING."
;; (interactive
;; (let ((word (current-word nil t)))
;; (list
;; (completing-read
;; (concat "OpenGL.org HLSL man page: (" word "): ")
;; (hlsl-man-completion-list)
;; nil nil nil nil word))))
;; (save-excursion
;; (apply hlsl-browse-url-function
;; (list (concat hlsl-man-pages-base-url thing ".xhtml")))))
;; TODO: Maybe remove easy menu?
(easy-menu-define hlsl-menu hlsl-mode-map
"HLSL Menu."
`("HLSL"
["Comment Out Region" comment-region
(c-fn-region-is-active-p)]
["Uncomment Region" (comment-region (region-beginning)
(region-end) '(4))
(c-fn-region-is-active-p)]
["Indent Expression" c-indent-exp
(memq (char-after) '(?\( ?\[ ?\{))]
["Indent Line or Region" c-indent-line-or-region t]
["Fill Comment Paragraph" c-fill-paragraph t]
"----"
["Backward Statement" c-beginning-of-statement t]
["Forward Statement" c-end-of-statement t]
"----"
["Up Conditional" c-up-conditional t]
["Backward Conditional" c-backward-conditional t]
["Forward Conditional" c-forward-conditional t]
"----"
["Backslashify" c-backslash-region (c-fn-region-is-active-p)]
"----"
["Find HLSL Man Page" hlsl-find-man-page t]
))
;;;###autoload
(define-derived-mode hlsl-mode prog-mode "HLSL"
"Major mode for editing HLSL shader files."
(c-initialize-cc-mode t)
(setq abbrev-mode t)
(c-init-language-vars-for 'c-mode)
(c-common-init 'c-mode)
(cc-imenu-init cc-imenu-c++-generic-expression)
(set (make-local-variable 'font-lock-defaults) '(hlsl-font-lock-keywords))
(set (make-local-variable 'ff-other-file-alist) 'hlsl-other-file-alist)
(set (make-local-variable 'comment-start) "// ")
(set (make-local-variable 'comment-end) "")
(set (make-local-variable 'comment-padding) "")
;; TODO: Indentation rules for annotated for loops, e.g:
;; [unroll] for (...) {
;; --->|
;; }
;; Currently it just indents flat as though no scope was declared
(add-to-list 'align-c++-modes 'hlsl-mode)
(c-run-mode-hooks 'c-mode-common-hook)
(run-mode-hooks 'hlsl-mode-hook)
;; TODO: Guard `c-make-noise-macro-regexps' based on Emacs version, then lower
;; dependency.
:after-hook (progn (when (fboundp 'c-make-noise-macro-regexps)
;; Depends on Emacs 26.1, guarding this allows us to
;; support down to Emacs 24.4
(c-make-noise-macro-regexps))
(c-make-macro-with-semi-re)
(c-update-modeline)))
;; TODO: Float number highlighting (i.e. 1.0f)
;; TODO: Negative number highlighting
;; TODO: Highlight numbers adjacent to operators e.g. 1-variable
(provide 'hlsl-mode)
;;; hlsl-mode.el ends here

197
local-lisp/move-text.el Normal file
View file

@ -0,0 +1,197 @@
;;; move-text.el --- Move current line or region with M-up or M-down. -*- lexical-binding: t; -*-
;; filename: move-text.el
;; Description: Move current line or region with M-up or M-down.
;; Author: Jason Milkins <jasonm23@gmail.com>
;; Keywords: edit
;; Url: https://github.com/emacsfodder/move-text
;; Compatibility: GNU Emacs 25.1
;; Version: 2.0.10
;;
;;; This file is NOT part of GNU Emacs
;;; License
;;
;; 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, 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; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;; Commentary:
;;
;; MoveText 2.0.0 is a re-write of the old move-text and compatible with >= Emacs 25.1
;;
;; It allows you to move the current line using M-up / M-down if a
;; region is marked, it will move the region instead.
;;
;; Using the prefix (C-u *number* or META *number*) you can predefine how
;; many lines move-text will travel.
;;
;;; Installation:
;;
;; Put move-text.el to your load-path.
;; The load-path is usually ~/elisp/.
;; It's set in your ~/.emacs like this:
;; (add-to-list 'load-path (expand-file-name "~/elisp"))
;;
;; And the following to your ~/.emacs startup file.
;;
;; (require 'move-text)
;; (move-text-default-bindings)
;;; Acknowledgements:
;;
;; Original v1.x was a Feature extracted from basic-edit-toolkit.el - by Andy Stewart (LazyCat)
;;
;;; Code:
(require 'cl-lib)
(defun move-text-get-region-and-prefix ()
"Get the region and prefix for the `interactive' macro, without aborting.
Note: `region-beginning' and `region-end' are the reason why an
`interactive' macro with \"r\" will blow up with the error:
\"The mark is not set now, so there is no region\"
We check with `use-region-p' to avoid calling
them when there's no region or it is not appropriate
to act on it.
We use `prefix-numeric-value' to return a number.
"
(list
(when (use-region-p) (region-beginning)) ;; otherwise nil
(when (use-region-p) (region-end))
(prefix-numeric-value current-prefix-arg)))
;;;###autoload
(defun move-text--total-lines ()
"Convenience function to get the total lines in the buffer / or narrowed buffer."
(line-number-at-pos (point-max)))
;;;###autoload
(defun move-text--at-first-line-p ()
"Predicate, is the point at the first line?"
(= (line-number-at-pos) 1))
;;;###autoload
(defun move-text--at-penultimate-line-p ()
"Predicate, is the point at the penultimate line?"
(= (line-number-at-pos) (1- (move-text--total-lines))))
;; save-mark-and-excursion in Emacs 25 works like save-excursion did before
(eval-when-compile
(when (< emacs-major-version 25)
(defmacro save-mark-and-excursion (&rest body)
`(save-excursion ,@body))))
;;;###autoload
(defun move-text--last-line-is-just-newline ()
"Predicate, is last line just a newline?"
(save-mark-and-excursion
(goto-char (point-max))
(beginning-of-line)
(= (point-max) (point))))
;;;###autoload
(defun move-text--at-last-line-p ()
"Predicate, is the point at the last line?"
(= (line-number-at-pos) (move-text--total-lines)))
;;;###autoload
(defun move-text-line-up ()
"Move the current line up."
(interactive)
(if (move-text--at-last-line-p)
(let ((target-point))
(kill-whole-line)
(forward-line -1)
(beginning-of-line)
(setq target-point (point))
(yank)
(unless (looking-at "\n")
(newline))
(goto-char target-point))
(let ((col (current-column)))
(progn (transpose-lines 1)
(forward-line -2)
(move-to-column col)))))
;;;###autoload
(defun move-text-line-down ()
"Move the current line down."
(interactive)
(unless (or
(move-text--at-last-line-p)
(and
(move-text--last-line-is-just-newline)
(move-text--at-penultimate-line-p)))
(let ((col (current-column)))
(forward-line 1)
(transpose-lines 1)
(forward-line -1)
(move-to-column col))))
;;;###autoload
(defun move-text-region (start end n)
"Move the current region (START END) up or down by N lines."
(interactive (move-text-get-region-and-prefix))
(let ((line-text (delete-and-extract-region start end)))
(forward-line n)
(let ((start (point)))
(insert line-text)
(setq deactivate-mark nil)
(set-mark start))))
;;;###autoload
(defun move-text-region-up (start end n)
"Move the current region (START END) up by N lines."
(interactive (move-text-get-region-and-prefix))
(move-text-region start end (- n)))
;;;###autoload
(defun move-text-region-down (start end n)
"Move the current region (START END) down by N lines."
(interactive (move-text-get-region-and-prefix))
(move-text-region start end n))
;;;###autoload
(defun move-text-up (start end n)
"Move the line or region (START END) up by N lines."
(interactive (move-text-get-region-and-prefix))
(if (not (move-text--at-first-line-p))
(if (region-active-p)
(move-text-region-up start end n)
(cl-loop repeat n do (move-text-line-up)))))
;;;###autoload
(defun move-text-down (start end n)
"Move the line or region (START END) down by N lines."
(interactive (move-text-get-region-and-prefix))
(if (region-active-p)
(move-text-region-down start end n)
(cl-loop repeat n do (move-text-line-down))))
;;;###autoload
(defun move-text-default-bindings ()
"Bind `move-text-up' and `move-text-down' to M-up & M-down."
(interactive)
(global-set-key [M-down] 'move-text-down)
(global-set-key [M-up] 'move-text-up))
(provide 'move-text)
;;; move-text.el ends here