Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ This mode needs GNU Emacs 24.4.
* Better indentation support
* Help system
* REPL interaction
* imenu support
* ETags support
* `find-file-at-point` for module names
* Electricity (`electric-pair-mode` needs some context-sensitive help)
Expand Down
53 changes: 53 additions & 0 deletions README.tmp-imenu-notes
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
major modes:

The mode should specify how Imenu should find the definitions or
sections of a buffer, by setting up a buffer-local value for the
variable imenu-generic-expression, for the two variables
imenu-prev-index-position-function and
imenu-extract-index-name-function, or for the variable
imenu-create-index-function (see Imenu).

Macro: defvar-local variable value &optional docstring

This macro defines variable as a variable with initial value value
and docstring, and marks it as automatically buffer-local. It is
equivalent to calling defvar followed by
make-variable-buffer-local. variable should be an unquoted symbol.

22.5 Imenu

Imenu is a feature that lets users select a definition or section in
the buffer, from a menu which lists all of them, to go directly to
that location in the buffer. Imenu works by constructing a buffer
index which lists the names and buffer positions of the definitions,
or other named portions of the buffer; then the user can choose one of
them and move point to it. Major modes can add a menu bar item to use
Imenu using imenu-add-to-menubar.

Command: imenu-add-to-menubar name

This function defines a local menu bar item named name to run Imenu.

The usual and simplest way is to set the variable imenu-generic-expression:

Variable: imenu-generic-expression

This variable, if non-nil, is a list that specifies regular
expressions for finding definitions for Imenu. Simple elements of
imenu-generic-expression look like this:

(menu-title regexp index)

Here, if menu-title is non-nil, it says that the matches for this
element should go in a submenu of the buffer index; menu-title
itself specifies the name for the submenu. If menu-title is nil, the
matches for this element go directly in the top level of the buffer
index.

The second item in the list, regexp, is a regular expression (see
Regular Expressions); anything in the buffer that it matches is
considered a definition, something to mention in the buffer
index.

The third item, index, is a non-negative integer that indicates
which subexpression in regexp matches the definition’s name.
76 changes: 76 additions & 0 deletions nqp-mode.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
;;; perl6-mode.el --- Major mode for editing Perl 6 code -*- lexical-binding: t; -*-

;; Copyright (C) 2015 Hinrik Örn Sigurðsson <[email protected]>

;; Author: Hinrik Örn Sigurðsson <[email protected]>
;; URL: https://github.com/hinrik/perl6-mode
;; Keywords: languages
;; Version: 0.1-git
;; Package-Requires: ((emacs "24.4") (pkg-info "0.1"))

;; This file is not part of GNU Emacs.

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

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

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

;;; Commentary:

;; GNU Emacs 24 major mode for editing Perl 6 code.

;; Currently only provides very basic syntax highlighting.

;;; Code:

(declare-function pkg-info-version-info "pkg-info" (library))

(defgroup perl6 nil
"Major mode for editing Perl 6 code."
:prefix "perl6-"
:group 'language)

(require 'perl6-detect)
(require 'perl6-font-lock)
(require 'perl6-indent)
(require 'perl6-imenu)

;;;###autoload
(define-derived-mode perl6-mode prog-mode "Perl6"
"Major mode for editing Perl 6 code."
;; Syntaxification and font locking
(setq-local syntax-propertize-function #'perl6-syntax-propertize)
(add-hook 'syntax-propertize-extend-region-functions #'syntax-propertize-multiline nil 'local)
(setq-local font-lock-syntactic-face-function #'perl6-font-lock-syntactic-face)
(setq-local font-lock-defaults '(perl6-font-lock-keywords nil nil))
;; Add imenu support for perl6-mode. Note that imenu-generic-expression
;; is buffer-local, so we don't need a local-variable for it.
(add-hook 'perl6-mode-hook 'imenu-add-menubar-index)
(setq imenu-generic-expression perl6-imenu-generic-expression
imenu-case-fold-search nil)
;; Comments
(setq-local comment-start "#")
(setq-local comment-start-skip "#+ *")
(setq-local comment-use-syntax t)
(setq-local comment-end "")
;; Indentation
(smie-setup perl6-smie-grammar #'perl6-smie-rules
:forward-token #'perl6-smie--forward-token
:backward-token #'perl6-smie--backward-token))

(provide 'perl6-mode)

;; Local Variables:
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:

;;; perl6-mode.el ends here
1 change: 1 addition & 0 deletions perl6-detect.el
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

;;;###autoload
(add-to-list 'auto-mode-alist '("\\.p[lm]?6\\'" . perl6-mode))
(add-to-list 'auto-mode-alist '("\\.nqp\\'" . perl6-mode))

;;;###autoload
(defconst perl6-magic-pattern
Expand Down
93 changes: 93 additions & 0 deletions perl6-imenu.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
;;; perl6-imenu.el --- Imenu support Perl 6 -*- lexical-binding: t; -*-

;; Imenu functions and variables are defined here.

;; Definition of "identifiers" (names) from
;; https://docs.perl6.org/language/syntax#Identifiers
;;
;; Identifiers are a grammatical building block that occur in several
;; places. An identifier is a primitive name, and must start with an
;; alphabetic character (or an underscore), followed by zero or more
;; word characters (alphabetic, underscore or number). You can also
;; embed dashes - or single quotes ' in the middle, but not two in a
;; row, and only if followed immediately by an alphabetic character.
;;
;; For NQP names, no embedded hyphens or single quotes are allowed.

;; Regex definitions:
(defvar perl6-name-regex
(concat
"[_[:alpha:]]" ; mandatory leading character
"\\(?:[-']?[[:alpha:]]\\|[_[:alnum:]]\\)*" ; rest of the name allowing embedded hyphens or single quotes
))

(defvar nqp-name-regex
(concat
"[_[:alpha:]]" ; mandatory leading character
"[_[:alnum:]]*" ; rest of the name (stricter than Perl 6 name)
))

(defvar perl6-vars-regex
(concat
"^\\s-*" ; leading ws allowed
"\\(?:my\\|our\\)\\s-+" ; scope of var, followed by mandatory ws
"\\(" ; start capture group 1 for the var name
"\\(?:\\$\\|@\\|%\\)" ; sigil for type of var
"\\(?:" ; start shy group for choice of one type name
perl6-name-regex
"\\|"
nqp-name-regex
"\\)" ; end shy group
"\\)" ; end of capture group 1
))

(defvar perl6-subs-regex
(concat
"^\\s-*" ; leading ws allowed
"\\(?:my\\s-+\\|our\\s-+\\)?" ; optional specific scope followed by at least one space
; must have one of the five type identifiers
; followed by at least one space:
"\\(?:multi\\s-+sub\\|multi\\s-+method\\|sub\\|method\\|multi\\|proto\\)\\s-+"
"\\!?" ; optional private marker
"\\(" ; start capture group 1 for the sub name
perl6-name-regex
"\\|"
nqp-name-regex
"\\)" ; end of capture group 1
))

(defvar perl6-classes-regex
(concat
"^\\s-*" ; leading ws allowed
; must have one of the four type identifiers followed by at least one space:
"class\\s-+"
"\\(" ; start capture group 1 of the class name
perl6-name-regex
"\\|"
nqp-name-regex
"\\)" ; end of capture group 1
))

(defvar perl6-imenu-generic-expression
`(
;; the names are in reverse desired order since they are evaluated here last first
("Classes" ,perl6-classes-regex 1)
("Variables" ,perl6-vars-regex 1)
("Subs/Methods" ,perl6-subs-regex 1)
)
"Define interesting points in the Perl 6 buffer for `imenu'.

This is used to set `imenu-generic-expression' when Perl 6 mode is
entered. Subsequent changes to `perl6-imenu-generic-expression' will
not affect existing Perl 6 buffers because imenu-generic-expression is
a local variable.")

;;===========================
(provide 'perl6-imenu)

;; Local Variables:
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:

;;; perl6-imenu.el ends here
6 changes: 6 additions & 0 deletions perl6-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
(require 'perl6-detect)
(require 'perl6-font-lock)
(require 'perl6-indent)
(require 'perl6-imenu)

;;;###autoload
(define-derived-mode perl6-mode prog-mode "Perl6"
Expand All @@ -50,6 +51,11 @@
(add-hook 'syntax-propertize-extend-region-functions #'syntax-propertize-multiline nil 'local)
(setq-local font-lock-syntactic-face-function #'perl6-font-lock-syntactic-face)
(setq-local font-lock-defaults '(perl6-font-lock-keywords nil nil))
;; Add imenu support for perl6-mode. Note that imenu-generic-expression
;; is buffer-local, so we don't need a local-variable for it.
(add-hook 'perl6-mode-hook 'imenu-add-menubar-index)
(setq imenu-generic-expression perl6-imenu-generic-expression
imenu-case-fold-search nil)
;; Comments
(setq-local comment-start "#")
(setq-local comment-start-skip "#+ *")
Expand Down
30 changes: 30 additions & 0 deletions perl6-unicode-menu.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
;; Provide a menu bar item to ease insertion of Unicode characters.


;; Make a menu keymap (with a prompt string)
;; and make it the menu bar item’s definition.
;; put it at the end
(define-key global-map [menu-bar unicode]
(cons "Unicode" (make-sparse-keymap "Unicode")))
;; Define specific subcommands in this menu.
(define-key global-map
[menu-bar unicode forward]
'("Forward word" . forward-word))
(define-key global-map
[menu-bar unicode backward]
'("Backward word" . backward-word))
(defvar menu-bar-final-items '(help-menu unicode-menu)) ;; doesn't work??





;;===========================
(provide 'perl6-unicode-menu)

;; Local Variables:
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:

;;; perl6-imenu.el ends here
24 changes: 24 additions & 0 deletions test/test-imenu.nqp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# file: test-imenu.p6

# Perl 6 syntax file for testing perl6-mode with imenu support, which is located at:
#
# https://github.com/tbrowder/perl6-mode [branch: "my-branch"]

my $a;
my @b;
our %c;

my $a-a;
my $a'a_3-z;

sub a(){my @ze}
multi sub x() {}
method d() {}
my multi method z() {}
multi c() {}

proto xx() {}

class My-class1 {}
class My-class2{
class doit () {}
24 changes: 24 additions & 0 deletions test/test-imenu.p6
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# file: test-imenu.p6

# Perl 6 syntax file for testing perl6-mode with imenu support, which is located at:
#
# https://github.com/tbrowder/perl6-mode [branch: "my-branch"]

my $a;
my @b;
our %c;

my $a-a;
my $a'a_3-z;

sub a(){my @ze}
multi sub x() {}
method d() {}
my multi method z() {}
multi c() {}
proto xx() {}
multi method !z-private() {}

class My-class1 {}
class My-class2{
class doit () {}