7

Q: I have the following Yasnippet, which looks like this:

 MYNAME - $1 (`(insert-mode-description)`).
 $2

When I insert the snippet, the cursor starts on $1. Then I begin with typing. I would like to convert the first character of the sentence that I'm typing to uppercase.

When I look in the documentation of Yasnippet, there is a transformer that converts your text to uppercase. I need only to capitalize the first character.

Then I figured out another option:

MYNAME - $1 $2 (`(insert-mode-description)`).
$3

So Everything in $1-place gets converted to uppercase. Then press tab, to jump to $2 and typing further in lowercase letters. But I'm not looking for that. Then I need to press tab every time after I insert the first character. I would just convert the first character of $1 to be uppercase. Any suggestion?

Drew
  • 75,699
  • 9
  • 109
  • 225
ReneFroger
  • 3,855
  • 22
  • 63

3 Answers3

8

Function to capitalize only the first char

Make sure that the below function is evaluated in your emacs config before the yasnippet snippets are loaded.

(defun my/capitalize-first-char (&optional string)
  "Capitalize only the first character of the input STRING."
  (when (and string (> (length string) 0))
    (let ((first-char (substring string nil 1))
          (rest-str   (substring string 1)))
      (concat (capitalize first-char) rest-str))))

Snippet

Here is a snippet that makes use of the above function

# -*- mode: snippet -*-
# name: intro
# key: zname
# --
Hi, my name is ${1:$$(my/capitalize-first-char yas-text)}.
$0

Demo

enter image description here Reference

Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
  • Thank for your addition. Hmmz, I will figure out if I could write a function for that. I will study the structure of upcase-initiials. If anyone knows another solution, I'm all ears! – ReneFroger May 22 '15 at 15:10
  • You can write a function that takes in a string, then you grab a substring from that till the first space character and apply `upcase-initials` only on that substring. I'll update the answer when I get a change to write that fn. – Kaushal Modi May 22 '15 at 16:37
  • I was already thinking about that, but I had some difficulties how to get the one first character only, then stop with convert them to uppercase. If you know another way, I'm trying your update now. – ReneFroger May 22 '15 at 21:34
  • Can you clarify? The current elisp snippet in my solution does upcase only the first char of $1 field of the snippet. – Kaushal Modi May 22 '15 at 21:37
  • I have copied the snippet and the function above exactly as you described it. When I start with typing, I got an error: `Hi, my name is [yas] elisp error: Wrong type argument: integerp, nil.` – ReneFroger May 22 '15 at 22:02
  • Hmm.. I had verified this to work, both function and the snippet.. Will check again tomorrow. In the meanwhile, does `M-: (my/capitalize-first-char "abc def")` work for you? – Kaushal Modi May 23 '15 at 03:35
  • @ReneFrogertjuh Added a demo gif that uses the code in the above solution. Works fine. Couple of things that you can check: (1) Ensure that the elisp function is evaluated (best way to do so is to copy that to your init.el and restart emacs) (2) Ensure that you saved the snippet as a SOME.snippet file in that major mode's `snippets/` folder (3) Do `M-x yas-reload-all` after that (4) Ensure that the `yas-minor-mode` is enabled in that major-mode buffer (5) Type the snippet key (`zname` in this case) and expand the snippet using your binding or `M-x yas-snippet`. – Kaushal Modi May 23 '15 at 15:13
  • Typo in the 5th point above.. I meant `M-x yas-expand`. – Kaushal Modi May 23 '15 at 16:04
  • Checked the video, followed all the steps, restarted Emacs, yas-reload all, snippet in folder of major mode (modified the `my name is` to `my name2 is` to double-check), `yas-expand`. After expanding the snippet, I got the same error from your snippet and the written function as copied. I don't understand why it works in your example. I tried M-: (my/capitalize-first-char "abc def") and I got the same error. I copied the error from the backtrace: http://pastebin.com/c21rCVpd So I'm wondering why it's working in your case? Any suggestion. I deeply appreciate your support, by the way. – ReneFroger May 24 '15 at 13:53
  • I decided to mark your answer as validate one, by the way. Your solution is propably working for the others, and the error is propably related with my setup. – ReneFroger May 25 '15 at 17:46
  • @ReneFrogertjuh Thanks. But we will try to get this working for you once I am back at a PC. What is your emacs version? I'll test this solution on that. – Kaushal Modi May 25 '15 at 19:21
  • Slightly less efficient, but you can replace most, if not all of the logic of `my/capitalize-first-char` with `(replace-regexp-in-string (rx bos nonl) #'capitalize string)`. – Basil Feb 08 '18 at 16:19
2

You may find a working solution here.

Function

(defun capitalizeFirst (s)
  (if (> (length s) 0)
      (concat (upcase (substring s 0 1)) (downcase (substring s 1)))
    nil))

Again put this function to your .emacs file before yasnippet initialization.

Snippet

# -*- mode: snippet -*-
# name: name
# key: name
# --
Hi, my name is ${1:$$(capitalizeFirst yas-text)}

Also some countries use different locales. According to Turkish locale if you convert ırak word which means far, distant to uppercase it should be converted like this Irak.

Here is a function which converts the first character of a string uppercase correctly according to Turkish locale.

Function which converts first character according to Turkish locale

(defun buyukHarfYap (metin)
  (let (ilkHarf sesliMi)
    (if (> (length metin) 0)
        (progn

          (setq ilkHarf (aref metin 0))

          (if (eq ilkHarf 105) ; i harfi
              (aset metin 0 ?İ))

          (if (eq ilkHarf 305) ; ı harfi
              (aset metin 0 ?I))

          (if (eq ilkHarf 97)  ; a harfi
              (aset metin 0 ?A))

          (if (eq ilkHarf 101) ; e harfi
              (aset metin 0 ?E))

          (if (eq ilkHarf 252) ; ü harfi
              (aset metin 0 ?Ü))

          (if (eq ilkHarf 111) ; o harfi
              (aset metin 0 ?O))

          (if (eq ilkHarf 246)
              (aset metin 0 ?Ö)); ö harfi

          (if (eq ilkHarf 117)
              (aset metin 0 ?U)); u harfi

          (setq ilkHarf (substring metin 0 1))

          (setq sesliMi (string-match ilkHarf "AEIİOÖUÜ"))

          (if (eq sesliMi nil)
              (concat (upcase(substring metin 0 1))  (downcase (substring metin 1)))
            (concat (substring metin 0 1)  (downcase (substring metin 1)))))nil)))
0

Regarding the capitalization part, you can also use s-capitalized-words of the s.el library, which is a handy string library.

whatacold
  • 843
  • 6
  • 10