1

I want to make Emacs aware of the language I input -- in my case, Arabic, English, German -- so that I can use different fonts for each of them. So, for example, I'd like Emacs to use the following fonts when I'm entering text in the following languages:

Arabic  - DejaVu Sans Mono 14  
English - Consolas 11  
German  - Consolas 12  

So:

  • How can I set this up in my init file?
  • Where do I find the exact names of languages in Emacs to be recognized by the code?

(Side note: I'm new to Emacs and am just starting to learn elisp.)

Clarifying to follow-up on comments:

  • I'm using Windows. Ideally, I'd like Emacs to understand what language I'm using based on the Language Bar.

Update:
A better approach to this problem is posted here.

Drew
  • 75,699
  • 9
  • 109
  • 225
doctorate
  • 1,789
  • 16
  • 39
  • Do you mean your operating system's current [IME](https://en.wikipedia.org/wiki/Input_method)? The currently set keyboard layout? Or are you asking for something that would somehow recognize what language you're inputting, no matter what the operating system level options are (like, it should recognize if you're typing german, even if your keyboard layout is english)? – wasamasa Nov 14 '14 at 13:17
  • yes to the latter. I am using Windows, based on the language shown in the `Language bar`, i.e., the input language no matter what keyboard layout you have. – doctorate Nov 14 '14 at 13:36
  • Good luck with that then, Emacs surely doesn't expose such functionality (it just receives keysyms, really) and Windows probably has an API call somewhere an external program needs to use. Or an external program could detect such changes (or be invoked directly on changes) and execute code in the running Emacs instance if you were using the daemon. – wasamasa Nov 14 '14 at 13:43
  • Alternatively you could forego size changes for English and German and instead set up DejaVu Sans Mono to be always used for arabic glyphs, this can be set up with fontsets for glyph ranges. However, [all fontset recources I've encountered until now are targeted at Linux users](http://www.emacswiki.org/emacs/FontSets), there's only [outdated information for Windows users available](http://www.emacswiki.org/emacs/FontSetsForNTEmacs). – wasamasa Nov 14 '14 at 13:46
  • 2
    Changing the font based on the language is actually rare — it's more common to change the font based on the *script* (so German and English would use one font, while Arabic and Persian would use another). Emacs supports different fonts for different scripts through [fontsets](http://www.gnu.org/software/emacs/manual/html_node/emacs/Fontsets.html). If you change the input language, do you want to change the font for subsequently inserted text only? For the current buffer/window/frame? For all buffers/windows/frames? – Gilles 'SO- stop being evil' Nov 16 '14 at 00:15
  • @Gilles, imagine you have a buffer containing both English and Arabic text. The question is what is best way to make Emacs smart enough to recognize language based on input text and then changing the font accordingly? – doctorate Nov 17 '14 at 09:24
  • @doctorate Your comment is as ambiguous as your question. Suppose you type a sentence in Arabic, then in the same buffer you type a sentence in English. Do you want to switch the font for the whole buffer, or just for the second sentence? – Gilles 'SO- stop being evil' Nov 17 '14 at 10:57
  • @Gilles, sorry for any ambiguity, just for the second sentence. – doctorate Nov 17 '14 at 12:10
  • @doctorate Ok. Next question: if you yank (paste) some text which is one English sentence and one Arabic sentence, in what font should the yanked text be? The current font? The English in your English font and the Arabic in your Arabic font? And if you open a file containing mixed English and Arabic, what font(s) should the buffer use? – Gilles 'SO- stop being evil' Nov 17 '14 at 12:36
  • @Gilles, In case of yanking, it should keep the font of the *copied* text. Anything else should follow the currently active keyboard layout whatever set by the user. – doctorate Nov 17 '14 at 12:42
  • @doctorate I'm talking about yanking text without any formatting, so no font indication. And what about the case of opening a text file? – Gilles 'SO- stop being evil' Nov 17 '14 at 12:47
  • @Gill to answer your last question, depends on whether your code is intended to be language-bar-aware or not. if it will somehow recognize the currently active keyboard layout in the machine, then it will follow that keyboard layout no matter what file you open. – doctorate Nov 17 '14 at 12:53
  • @Gilles another approach may be, to set a default value say English and font1, but then if someone would like to write in a another language it will change to the corresponding font somehow. – doctorate Nov 17 '14 at 12:55
  • I still don't understand whether you want to use the font as a visual indicator of the current keyboard setting, or if you want to use different fonts for Arabic characters and Latin characters. – Gilles 'SO- stop being evil' Nov 17 '14 at 14:40
  • Ok, please edit your question to clarify it. And [fontsets](http://www.gnu.org/software/emacs/manual/html_node/emacs/Fontsets.html) are probably what you're looking for. – Gilles 'SO- stop being evil' Nov 17 '14 at 15:18

1 Answers1

1

In the comments you said you wanted to depend on the Windows language bar. The Windows Get-WinDefaultInputMethodOverride Cmdlet in Window PowerShell provides the necessary information.

Thus, when creating a new buffer, you need to run PowerShell Get-WinDefaultInputMethodOverride and parse the ouput. If you do this for every buffer, even for temporary buffers, my guess is that this slow you down very much. It would be better to write a function that can be added to hooks such as find-file-hooks. The functions on this hook are only called when you open a file for editing.

Calling a command and capturing the output happens using (shell-command-to-string COMMAND). Comparing a string to some other values happens via (string-match REGEXP STRING). Setting the font for a particular buffer involves calling (face-remap-add-relative FACE &rest SPECS). The face you are interested in is called default. The specs you want are :family and :height, the font family and the font size in tenths of points.

Thus, perhaps (untested, since I'm not on Windows):

(defun my-buffer-setup ()
  (let ((output (shell-command-to-string "PowerShell Get-WinDefaultInputMethodOverride")))
    (cond ((string-match "arabic" output)
           (face-remap-add-relative 'default :family "DejaVu Sans Mono" :height 140))
          ((string-match "english" output)
           (face-remap-add-relative 'default :family "Consolas" :height 110))
          ((string-match "german" output)
           (face-remap-add-relative 'default :family "Consolas" :height 120)))))

(add-hook 'find-file-hook 'my-buffer-setup)

Good luck. :)

Alex Schröder
  • 356
  • 1
  • 4
  • About your choice of hook – I'll often create temporary buffers for notes. These aren't associated with any file, so `find-file-hook` is never run. – Sean Allred Nov 16 '14 at 14:32
  • @SeanAllred Yeah, the correct solution depends on how you want to use Emacs. You could look at `buffer-list-update-hook`. – Alex Schröder Nov 17 '14 at 08:15
  • I could not test it either bcz this powershell command was first introducted in Win8 and it seems there is no equivalent in win7. My machine has Ubuntu too, can you please extend this function to recognize system on machine and run the corresponding function based on system used? I would like to test it on Ubuntu first and meanwhile I have to look for the correct cmd command to inquire about the input lanugage in Windwos 7 32bit. – doctorate Nov 17 '14 at 09:29
  • Somebody else will have to do this, as I don't have access to those systems. – Alex Schröder Nov 17 '14 at 10:28
  • @AlexSchröder, as a workaround can you please care to answer the post here: http://emacs.stackexchange.com/questions/5519/how-to-assign-a-certain-font-for-each-text-input-method-in-emacs-24 – doctorate Dec 18 '14 at 07:51