Mapping source code line number to "printed" page number - emacs

Sometimes I search in emacs for some variable then try to find which page should I look for in the printout of the file I have in hand.
Is it possible, given the printing parameters I use, to have emacs show a "virtual" page number that maps to the where the cursor is pointing at?
I am trying to play with the "mode line", given that each printed page has 72 lines, then page number = line_number/72+1.
This did not work though:
(setq-default mode-line-format
'("" mode-line-modified ""
mode-line-buffer-identification "-"
"[" mode-name "." mode-line-process "." minor-mode-alist "" "%n" "]"
line-number-mode "-" "L%l"
"-" "P" (+ 1 (/ %l 72))
column-number-mode "-" "C%c"
mode-line-misc-info ""
abbreviated-file-name
"%-"
)
)
Anny pointers?

You can force mode-line updates (force-mode-line-update) with something like the post-command-hook.
(setq-default mode-line-format '(
" "
(:eval (format "Line %s | Page %s"
(line-number-at-pos) (+ 1 (/ (line-number-at-pos) 72)) ))))

Related

how to import a hash-table into an org-mode in emacs?

I have a hash-table and would like to export the hash-tables into an org-buffer.
What the hash-table should print out to an org-buffer:
take the keys, if the key's value is not a hash then it's ":: " otherwise if the key's value is a hash-table then the key is a heading and so on.
Q.
1. I couldn't find if there is an 'import' into the org-buffer implemented already. If there is, can someone point me to it?
2. Has someone written anything similar to this? I can do it (it seems simple enough) but would hate to reinvent the wheel. If there is a library already out there that can take a structure (hash-table) and import it into an org-buffer, that would be awesome.
Thanks.
I have provided an example of the output of what that hash-table should be represented into the org-buffer and the raw hash-table.
* key "project-example"
:id: "12345"
** affected-versions
:id: "12332"
:name: "SlimShady"
:archived: nil
:release-date: "2014-10-01T04:00:00.000Z"
:released: nil
:sequence: 81
:assigned-to: "m&m"
:attach-name: nil
** components
:id: "3214"
:name: "Dr.Dre"
:created: "2014-11-13T15:49:15.000Z"
** customer-fld-vals:
:custom-fld-id: "cust-id-112233"
:key: nil
:values: "Fill me"
:description: nil
:duedate: nil
:environment: nil
:fixVersions: nil
:key: "project-example"
:priority: "high"
:project: "EX"
:reporter: "YourName"
:resolution: "xx"
:status: "xx"
:summary: "Write something here"
:type: "xx"
:updated: "2014-11-15T22:52:13.000Z"
:votes: 0
Raw-hash (i have a list which has only one hash in it):
((hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data
(id "12345" affected-versions #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data
(id "12332" name "SlimShady" archived nil release-date "2014-10-01T04:00:00.000Z" released nil sequence 81))
assigned-to "m&m" attach-name nil components #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data
(id "3214" name "Dr.Dre"))
created "2014-11-13T15:49:15.000Z" customer-fld-vals #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data
(customfieldId "cust-id-112233" key nil values
("Fill me")))
description nil duedate nil environment nil fixVersions nil key "project-example" priority "high" project "EX" reporter "YourName" resolution "xx" status "xx" summary "Write something here" type "xx" updated "2014-11-15T22:52:13.000Z" votes 0)))
I have stolen you all the fun;-). The output is a bit different to what you suggested. I do not indent the headers of the leaves so that org recognizes the structure.
(defun org-import-hash (title hash &optional level noindent)
"Import HASH table into an org buffer.
Put TITLE into the first heading.
The hash table starts with LEVEL where LEVEL defaults to 1.
Indent inserted region by org-mode unless NOINDENT is non-nil."
(interactive "sTitle:\nXHash-table:")
(unless level (setq level 1))
(let ((b (point)))
(insert (if (or (looking-back "\n") (= (point) 1)) "" "\n") (make-string level ?*) (format " %s\n" title))
(maphash (lambda (key val)
(cond
((hash-table-p val)
(org-import-hash key val (1+ level) t))
;; other special cases here
(t
(insert (format " :%s: %s\n" key val)))
))
hash)
(unless noindent
(indent-region b (point)))
))
The comment section would not allow me extra characters so I couldn't post this code there.
Thank you for your solution, it's neat!!
I am new to elisp and do not know all the functions properly. Really like the 'make-string', my alternative is that I keep a list of stars per heeding and then concat them wherever necessary.
I came up with solution shortly after i asked the question. I like your approach.
A few notes about my hash is that all the keys are symbols hence this: '(symbol-name k)'
(defun ->string (whatever)
(cond
((equal 'integer (type-of whatever)) (number-to-string whatever))
((equal 'cons (type-of whatever)) (mapconcat 'identity (mapcar '->string whatever) " " ))
((equal 'string (type-of whatever)) whatever)))
(defun out->print (dstring)
(print dstring))
(defun out->buffer (dstring)
(insert dstring))
(defun print-issues (dhash stars)
(maphash (lambda (k v)
(progn (if (equal 'hash-table (type-of v))
(progn
(let ((nstars (cons "*" stars)))
(out->buffer (concat (apply 'concat nstars) " " (symbol-name k) "\n"))
(print-issues v nstars)))
(out->buffer (concat (replace-regexp-in-string "\*" "\s"
(apply 'concat stars))
":"
(symbol-name k)
":"
" -- "
(->string v) "\n")))))
dhash))

How to finish this job in emacs?

The original string is like this:
# chrom,name,strand,txStart
And the result should looks like this:
# $1: chrom
# $2: name
# $3: strand
# $4: txStart
Does anyone have idea of a quick way to do that?
Lots of ways.
You could use a search and replace making use of the \# counter in the replacement. That's zero-based, so you'd either need to add a dummy replacement at the front to use up the zero, or else use the elisp replacement expression \,(1+ \#) instead.
You could use a keyboard macro, and insert a counter with C-xC-kTAB or <f3>. You can seed that counter by supplying a prefix argument when you start recording.
On Emacs 24 you can number the lines of a marked region using a custom format string with C-uC-xrN, so your format string could be # $%1d:
Evaluate following code and execute foo function on input line.
(require 'cl)
(defun foo ()
(interactive)
(let* ((str (buffer-substring-no-properties
(line-beginning-position) (line-end-position)))
(words-str (and (string-match "# \\(.+\\)$" str)
(match-string 1 str)))
(buf (get-buffer-create "*tmp*")))
(unless words-str
(error "Line should be '# word1,word2,...'"))
(with-current-buffer buf
(erase-buffer)
(loop with index = 1
for word in (split-string words-str ",")
do
(progn
(insert (format "# $%d: %s\n" index word))
(incf index)))
(pop-to-buffer buf))))

emacs character before point equals

How to check whether the character before point equals "\"
(defun comment-latex ()
(interactive)
(if (region-active-p)
(comment-region (region-beginning) (region-end))
(if (= (char-before) ("\\") ;; how to fix this sentence?
(insert "%")
(if (= (point) (line-beginning-position)) ;; this part works
(insert "% ")
(end-of-line)
(insert " % "))))
)
(global-set-key LaTeX-mode-map (kbd "%") 'comment-latex)
The code as example should be doing the following:
1) If a region is selected, the region should be commented.
2) If the character before point is a "\", a normal % should be inserted at point.
3) If point is at the beginning of line, insert a "%"
4) If point is anywhere else, go to the end of the sentence and insert "SPC % SPC"
The syntax for individual characters is ?char. So:
(= (char-before) ?\\)
Replace it with
(= (char-before) 92)
92 is the ASCII code of the \ character.
In e-lisp, a character is not the same as a string. The syntax for getting the ascii value of a character is ?a. Try something like:
(if (= (char-before) ?\\))
DO-SOMETHING
DO-SOMETHING-ELSE)

Concat string with a specific operator

I am using Emacs, Notepad++ or Eclipse. Is there a way to cut a String in small pieces and concat them using a separator?
For instance:
Input:
"I like sushi and maki"
Output:
"I like" +
"sushi and" +
"maki"
In Eclipse (at least in the Java context) you only need to place the cursor inside the string and hit enter. This works also in Netbeans.
In Notepad++ you can use RegEx: ([\w]+)\s*([\w]*) and then replace with "$1 $2" + but then you will have to go back and remove the extraneous + signs from the end replacements that just have one group match.
Below is my take at the problem. Not sure if I'm solving the right problem though :)
(defun split-string-words (min max)
(interactive "r")
(let ((counted 0) (before-indent min)
(wordcount (read-number "How many words in a line? " 7))
(delimiter
(read-string "Delimit with (default: \" + \") "
nil nil "\" + \"")))
(save-excursion
(goto-char min)
(while (< min max)
(incf counted)
(when (= counted wordcount)
(insert delimiter)
(backward-char)
(incf max (length delimiter))
(setq before-indent (point)
counted 0)
(newline-and-indent)
(incf max (- (point) before-indent)))
(forward-word)
(setq min (point))))))
The use should be straight forward. Also check your editing mode for a <mode>-insert-and-indent function, you would like to use it instead of newline-and-indent.

Highlighting correctly in an emacs major mode

I am developing an emacs major mode for a language (aka mydsl). However, using the techniques on xahlee's site doesn't seem to be working for some reason (possibly older emacs dialect..)
The key issues I am fighting with are (1) highlighting comments is not working and (2), the use of regexp-opt lines is not working.
I've reviewed the GNU manual and looked over cc-mode and elisp mode... those are significantly more complicated than I need.
;;;Standard # to newline comment
;;;Eventually should also have %% to %% multiline block comments
(defun mydsl-comment-dwim (arg)
"comment or uncomment"
(interactive "*P")
(require 'newcomment)
(let
((deactivate-mark nil)
(comment-start "#")
(comment-end "")
comment-dwim arg)))
(defvar mydsl-events
'("reservedword1"
"reservedword2"))
(defvar mydsl-keywords
'("other-keyword" "another-keyword"))
;;Highlight various elements
(setq mydsl-hilite
'(
; stuff between "
("\"\\.\\*\\?" . font-lock-string-face)
; : , ; { } => # $ = are all special elements
(":\\|,\\|;\\|{\\|}\\|=>\\|#\\|$\\|=" . font-lock-keyword-face)
( ,(regexp-opt mydsl-keywords 'words) . font-lock-builtin-face)
( ,(regexp-opt mydsl-events 'words) . font-lock-constant-face)
))
(defvar mydsl-tab-width nil "Width of a tab for MYDSL mode")
(define-derived-mode mydsl-mode fundamental-mode
"MYDSL mode is a major mode for editing MYDSL files"
;Recommended by manual
(kill-all-local-variables)
(setq mode-name "MYDSL script")
(setq font-lock-defaults '((mydsl-hilite)))
(if (null mydsl-tab-width)
(setq tab-width mydsl-tab-width)
(setq tab-width default-tab-width)
)
;Comment definitions
(define-key mydsl-mode-map [remap comment-dwim] 'mydsl-comment-dwim)
(modify-syntax-entry ?# "< b" mydsl-mode-syntax-table)
(modify-syntax-entry ?\n "> b" mydsl-mode-syntax-table)
;;A gnu-correct program will have some sort of hook call here.
)
(provide 'mydsl-mode)
You have a couple of syntactic problems in your code, but you got it nearly correct. Here's my edited version which appears to do the right thing for a buffer in mydsl-mode:
; No changes to the simple vars
(defvar mydsl-events
'("reservedword1"
"reservedword2"))
(defvar mydsl-keywords
'("other-keyword" "another-keyword"))
;; I'd probably put in a default that you want, as opposed to nil
(defvar mydsl-tab-width nil "Width of a tab for MYDSL mode")
;; Two small edits.
;; First is to put an extra set of parens () around the list
;; which is the format that font-lock-defaults wants
;; Second, you used ' (quote) at the outermost level where you wanted ` (backquote)
;; you were very close
(defvar mydsl-font-lock-defaults
`((
;; stuff between "
("\"\\.\\*\\?" . font-lock-string-face)
;; ; : , ; { } => # $ = are all special elements
(":\\|,\\|;\\|{\\|}\\|=>\\|#\\|$\\|=" . font-lock-keyword-face)
( ,(regexp-opt mydsl-keywords 'words) . font-lock-builtin-face)
( ,(regexp-opt mydsl-events 'words) . font-lock-constant-face)
)))
(define-derived-mode mydsl-mode fundamental-mode "MYDSL script"
"MYDSL mode is a major mode for editing MYDSL files"
;; fundamental-mode kills all local variables, no need to do it again
(setq mode-name "MYDSL script")
;; you again used quote when you had '((mydsl-hilite))
;; I just updated the variable to have the proper nesting (as noted above)
;; and use the value directly here
(setq font-lock-defaults mydsl-font-lock-defaults)
;; when there's an override, use it
;; otherwise it gets the default value
(when mydsl-tab-width
(setq tab-width mydsl-tab-width))
;; for comments
;; overriding these vars gets you what (I think) you want
;; they're made buffer local when you set them
(setq comment-start "#")
(setq comment-end "")
(modify-syntax-entry ?# "< b" mydsl-mode-syntax-table)
(modify-syntax-entry ?\n "> b" mydsl-mode-syntax-table)
;;A gnu-correct program will have some sort of hook call here.
)
(provide 'mydsl-mode)