مرجع سريع

ورقة غش Vimscript

دليل مرجعي شامل لـ Vimscript: المتغيرات، الدوال، الأوامر المخصصة، هياكل البيانات، ربط المفاتيح وإبراز الصياغة.

· تاريخ النشر

Vimscript هي لغة البرمجة النصية المدمجة لتخصيص وتوسيع محرر النصوص Vim.

البدء السريع

let name = "John"
echo "Hello, " . name

يمكنك وضع هذا الكود في ملف (script.vim) وتحميله عبر (:source script.vim)، أو تنفيذ الأوامر مباشرة في الوضع العادي عبر :let و :echo.

التعلم عبر الأمثلة

function! SuperTab()
  let l:part = strpart(getline('.'), col('.') - 2, 1)
  if (l:part =~ '^\W\?$')
    return "\<Tab>"
  else
    return "\<C-n>"
  endif
endfunction

imap <Tab> <C-R>=SuperTab()<CR>

المتغيرات (Variables)

التعريف

let var = "hello"

بادئات نطاق المتغيرات (Variable Scope Prefixes)

let g:ack_options = '-s -H'    " g: global
let s:ack_program = 'ack'      " s: local (to script)
let l:foo = 'bar'              " l: local (to function)
let a:arg = 'baz'              " a: function argument

يمكن أيضاً استخدام البادئة s: لأسماء الدوال المحلية على مستوى الملف. راجع :help local-variables.

نطاقات أخرى

let w:foo = 'bar'    " w: window local
let b:state = 'on'   " b: buffer local
let t:state = 'off'  " t: tab page local
echo v:version       " v: vim internal variable
let @/ = ''          " @  register
echo $PATH           " $  environment variable

خيارات محرر Vim

echo 'tabstop is ' . &tabstop
if &insertmode
echo &g:option
echo &l:option

أضف الرمز & كبادئة لأسماء الخيارات لقراءتها أو تعديلها برمجياً داخل التعبيرات.

العمليات الحسابية وعمليات السلاسل النصية

a + b             " Numbers only!
'hello ' . name   " String concatenation
let var -= 2
let var += 5
let var .= 'string'

السلاسل النصية (Strings)

صياغة السلاسل النصية

let str = "String"
let str = "String with \n newline"

let literal = 'literal, no \ escaping'
let literal = 'that''s enough'

echo "result = " . res

دوال السلاسل النصية

strlen(str)
len(str)
strchars(str)

split("one two three")       "=> ['one', 'two', 'three']
split("one.two.three", '.')  "=> ['one', 'two', 'three']

join(['a', 'b'], ',')        "=> 'a,b'

tolower('Hello')
toupper('Hello')

الدوال (Functions)

تعريف الدوال

function! s:Initialize(cmd, args)
  echo "Command: " . a:cmd
  return 1
endfunction

إعادة كتابة الدوال (Overwriting)

function! MyFunc()
  echo "Function defined or replaced"
endfunction

استخدام function! (مع إشارة !) يستبدل أي دالة معرّفة مسبقاً بنفس الاسم دون إثارة أخطاء.

مساحات الأسماء والتحميل التلقائي (Autoload)

function! myplugin#hello()
  " autoload/myplugin.vim
endfunction

استدعاء الدوال

call s:Initialize()
call s:Initialize("hello", 123)

التقاط قيم الإرجاع

let result = s:Initialize()

الإيقاف الفوري عند حدوث أخطاء (Abort)

function! MyFunction() abort
endfunction

وسائط متغيرة العدد (Variadic Arguments)

function! Infect(...)
  echo a:0
  echo a:1
  echo a:2

  for item in a:000
    echon ' ' . item
  endfor
endfunction

call Infect('jake', 'bella')

الحلقات والتحكم في التدفق

الحلقات (Loops)

for s in list
  echo s
  continue
  break
endfor
while x < 5
  let x += 1
endwhile

الأوامر المخصصة (Custom Commands)

تعريف الأوامر

command! Save :set fo=want tw=80 nowrap

يجب أن تبدأ الأوامر المعرفة من قبل المستخدم بحرف كبير. يسمح خيار ! باستبدال أمر موجود مسبقاً.

استدعاء الدوال من الأوامر

command! Save call <SID>Foo()

function! s:Foo()
endfunction

وسائط الأوامر

command! -nargs=? Save call script#foo(<args>)
محدد الوسائط الوصف
-nargs=0 بدون وسائط (الافتراضي)
-nargs=1 وسيط واحد بالضبط (قد يحتوي مسافات)
-nargs=? صفر أو وسيط واحد
-nargs=* صفر أو أكثر من وسائط مفصولة بمسافات
-nargs=+ وسيط واحد أو أكثر مفصولة بمسافات

الشروط والمنطق (Conditionals)

If / Elseif / Else

let char = getchar()
if char == "\<LeftMouse>"
elseif char == "\<RightMouse>"
else
endif

القيم المنطقية والصحة (Truthiness)

if 1       "=> True
if 0       "=> False
if "1"     "=> True
if "456"   "=> True
if "xfz"   "=> False

لا يحتوي Vimscript على نوع منطقي منفصل: 0 يمثل خطأ وأي عدد صحيح غير صفري يمثل صواب.

معاملات المقارنة

if 3 > 2
if a && b
if (a && b) || (c && d)
if !c

تحسس حالة الأحرف في السلاسل النصية

if name ==# 'John'     " case-sensitive
if name ==? 'John'     " case-insensitive
if name == 'John'      " &ignorecase

مقارنة تطابق الكائن (Identity)

if a is b
if a isnot b

يتحقق مما إذا كان a و b يشيران إلى نفس الكائن تماماً في الذاكرة.

مطابقة التعبيرات النمطية (Regular Expressions)

"hello" =~ 'xx*'
"hello" !~ 'xx*'
"hello" =~ '\v<\d+>'

يقوم بتفعيل صياغة very magic للتعبيرات النمطية لتجنب الهروب الزائد للرموز.

العبارات في سطر واحد

if empty(a:path) | return [] | endif
let status = a ? b : c

استخدم الرمز | للفصل بين جمل برمجية متعددة في سطر واحد.

هياكل البيانات (Data Structures)

القوائم (Lists)

let mylist = [1, "two", 3, "four"]

let first = mylist[0]
let last  = mylist[-1]

let second = get(mylist, 1)
let fallback = get(mylist, 10, "NONE")

عمليات القوائم

len(mylist)
empty(mylist)

let sortedlist = sort(copy(mylist))

let shortlist = mylist[2:-1]
let shortlist = mylist[2:]
let single = mylist[2:2]

let longlist = mylist + [5, 6]
let mylist += [7, 8]
call add(mylist, 9)

دوال القوائم الوظيفية

call map(files, "bufname(v:val)")
call filter(files, 'v:val != ""')

القواميس (Dictionaries)

let colors = {
  \ "apple": "red",
  \ "banana": "yellow"
}

echo colors["apple"]
echo get(colors, "apple")

عمليات القواميس

call remove(colors, "apple")

if has_key(dict, 'foo')
if empty(dict)
let k = keys(dict)
let v = values(dict)
let n = len(dict)

echo max(dict)
echo min(dict)

call extend(s:fruits, { "cherry": "red" })
for key in keys(mydict)
  echo key . ': ' . mydict[key]
endfor

بادئات النطاق (s:, g:, l:, b:) يمكن الوصول إليها نفسها ككائنات قواميس:

let script_keys = keys(s:)

الأرقام والعمليات الحسابية

let int = 1000
let hex = 0xff
let oct = 0755
let fl = 100.1
let sci = 5.4e4
3 / 2     "=> 1
3 / 2.0   "=> 1.5
sqrt(100)
floor(3.5)
ceil(3.3)
abs(-3.4)

خصائص Vim المميزة

تنفيذ الأوامر (execute)

execute "vsplit"
execute "edit " . fnameescape(filename)

تنفيذ ضغطات الوضع العادي (normal)

normal G
normal! G

execute "normal! gg/foo\<cr>dd"

توسيع مسارات وأسماء الملفات

echo expand("%")      " path/file.txt
echo expand("%:t")    " file.txt
echo expand("%:p:h")  " /home/user/path
echo expand("%:r")    " path/file
echo expand("%:e")    " txt

التحكم في المخرجات والرسائل

silent g/pattern/p

echo 'Simple text'
echomsg 'Persistent text recorded in :messages'
echoerr 'Error message'

echohl WarningMsg | echomsg "=> Warning!" | echohl None

خيارات الإعدادات

set number
set nonumber
set number!
set numberwidth=5
set guioptions+=e

فحص البيئة واكتشاف الميزات

has("clipboard")
executable("python3")
globpath(&rtp, "syntax/c.vim")

exists("$ENV")
exists(":command")
exists("variable")
exists("+option")

ربط المفاتيح (Key Mappings)

أوضاع الربط

[nvixso](nore)map

أعلام الربط الشائعة

العلم (Flag) المعنى
<buffer> محلي للمخزن المؤقت الحالي فقط
<silent> عدم إظهار الأمر في شريط الحالة
<nowait> التنفيذ الفوري دون انتظار مدخلات أطول

إبراز الصياغة والإخفاء (Syntax & Conceal)

مجموعات التمييز (Highlight Groups)

hi Comment term=bold gui=bold ctermfg=4 guifg=#80a0ff
hi def link markdownH1 htmlH1

اكتشاف نوع الملف (Filetype Detection)

augroup filetypedetect
  au! BufNewFile,BufRead *.json setf javascript
augroup END

au Filetype markdown setlocal spell

الإخفاء التفاعلي (Conceal)

set conceallevel=2
syn match newLine "<br>" conceal cchar=}
hi newLine guifg=green

حماية تضمين الملفات (Include Guards)

if exists('g:loaded_myplugin')
  finish
endif
let g:loaded_myplugin = 1

موضوعات ذات صلة