Mô đun:Arguments/tài liệu

Bách khoa toàn thư mở Wikipedia

Mô-đun này cung cấp xử lý dễ dàng các đối số được truyền từ #invoke. Đây là một mô-đun meta, được sử dụng cho các mô-đun khác và không được gọi trực tiếp từ #invoke. Các tính năng của nó bao gồm:

  • Dễ dàng cắt xén các đối số và loại bỏ các đối số trống.
  • Đối số có thể được truyền bởi cả khung hiện tại và khung cha cùng một lúc. (Thêm chi tiết bên dưới.)
  • Các đối số có thể được truyền trực tiếp từ một mô-đun Lua khác hoặc từ bảng điều khiển gỡ lỗi.
  • Đối số được tìm nạp khi cần, điều này có thể giúp tránh (một số) sự cố với thẻ <ref>...</ref>.
  • Hầu hết các tính năng có thể được tùy chỉnh.

Sử dụng cơ bản[sửa mã nguồn]

Đầu tiên, bạn cần tải mô-đun. Nó chứa một hàm, được đặt tên getArgs.

local getArgs = require('Module:Arguments').getArgs

Trong kịch bản cơ bản nhất, bạn có thể sử dụng getArgs bên trong chức năng chính của mình. Biến args là bảng chứa các đối số từ #invoke. (Xem bên dưới để biết chi tiết.)

local getArgs = require('Module:Arguments').getArgs
local p = {}

function p.main(frame)
	local args = getArgs(frame)
	-- Main module code goes here.
end

return p

Tuy nhiên, thực tế nên đề xuất là sử dụng một hàm chỉ để xử lý các đối số từ #invoke. Điều này có nghĩa là nếu ai đó gọi mô-đun của bạn từ một mô-đun Lua khác, bạn không phải có sẵn một đối tượng khung, điều này giúp cải thiện hiệu suất.

local getArgs = require('Module:Arguments').getArgs
local p = {}

function p.main(frame)
	local args = getArgs(frame)
	return p._main(args)
end

function p._main(args)
	-- Main module code goes here.
end

return p

Nếu bạn muốn nhiều hàm sử dụng các đối số và bạn cũng muốn chúng có thể truy cập được từ #invoke, bạn có thể sử dụng hàm bao bọc.

local getArgs = require('Module:Arguments').getArgs

local p = {}

local function makeInvokeFunc(funcName)
	return function (frame)
		local args = getArgs(frame)
		return p[funcName](args)
	end
end

p.func1 = makeInvokeFunc('_func1')

function p._func1(args)
	-- Code for the first function goes here.
end

p.func2 = makeInvokeFunc('_func2')

function p._func2(args)
	-- Code for the second function goes here.
end

return p

Tùy chỉnh[sửa mã nguồn]

Một só Lựa chọn tùy chỉnh có sẵn khi sử dụng. Chúng được giải thích trong các phần dưới đây.

local args = getArgs(frame, {
	trim = false,
	removeBlanks = false,
	valueFunc = function (key, value)
		-- Code for processing one argument
	end,
	frameOnly = true,
	parentOnly = true,
	parentFirst = true,
	wrappers = {
		'Template:A wrapper template',
		'Template:Another wrapper template'
	},
	readOnly = true,
	noOverwrite = true
})

Cắt và loại bỏ khoảng trống[sửa mã nguồn]

Các đối số trống thường gây khó đối với các lập trình viên mới muốn chuyển đổi các bản mẫu MediaWiki sang Lua. Trong cú pháp bản mẫu, chuỗi trống và chuỗi chỉ bao gồm khoảng trắng được coi là sai. Tuy nhiên, trong Lua, chuỗi trống và chuỗi bao gồm khoảng trắng được coi là đúng. Điều này có nghĩa là nếu bạn không chú ý đến những lập luận như vậy khi bạn viết các mô-đun Lua của mình, bạn có thể coi điều gì đó là đúng mà thực sự nên được coi là sai. Để tránh điều này, theo mặc định, mô-đun này sẽ xóa tất cả các đối số trống.

Tương tự, khoảng trắng có thể gây ra vấn đề khi xử lý các đối số vị trí. Mặc dù khoảng trắng được cắt bớt cho các đối số được đặt tên đến từ #invoke, nhưng nó được giữ nguyên cho các đối số vị trí. Hầu hết thời gian khoảng trắng bổ sung này là không mong muốn, vì vậy mô-đun này cắt nó theo mặc định.

Tuy nhiên, đôi khi bạn muốn sử dụng các đối số trống làm đầu vào và đôi khi bạn muốn giữ khoảng trắng bổ sung. Điều này có thể cần thiết để chuyển đổi một số mẫu chính xác như chúng đã được viết. Nếu bạn muốn làm điều này, bạn có thể đặt trimremoveBlanks với tham số là false.

local args = getArgs(frame, {
	trim = false,
	removeBlanks = false
})

Định dạng tùy chỉnh của các đối số[sửa mã nguồn]

Đôi khi bạn muốn xóa một số đối số trống nhưng không phải là đối số khác hoặc có lẽ bạn muốn đặt tất cả các đối số vị trí ở dạng chữ thường. Để làm những việc như thế này bạn có thể sử dụng tùy chọn valueFunc. Đầu vào của tùy chọn này phải là một hàm có hai tham số, keyvalue, và trả về một giá trị duy nhất. Giá trị này là những gì bạn sẽ nhận được khi truy cập vào trường key trong bảng args.

Ví dụ 1: hàm này bảo toàn khoảng trắng cho đối số vị trí đầu tiên, nhưng cắt bỏ tất cả các đối số khác và loại bỏ tất cả các đối số trống khác.

local args = getArgs(frame, {
	valueFunc = function (key, value)
		if key == 1 then
			return value
		elseif value then
			value = mw.text.trim(value)
			if value ~= '' then
				return value
			end
		end
		return nil
	end
})

Ví dụ 2: hàm này loại bỏ các đối số trống và chuyển đổi tất cả các đối số thành chữ thường, nhưng không cắt khoảng trắng khỏi các tham số vị trí.

local args = getArgs(frame, {
	valueFunc = function (key, value)
		if not value then
			return nil
		end
		value = mw.ustring.lower(value)
		if mw.ustring.find(value, '%S') then
			return value
		end
		return nil
	end
})

Lưu ý: các chức năng trên sẽ thất bại nếu đầu vào không thuộc loại string hoặc nil. Đây có thể là trường hợp nếu bạn sử dụng chức năng getArgs trong chức năng chính của mô-đun của bạn và chức năng đó được gọi bởi một mô-đun Lua khác. Trong trường hợp này, bạn sẽ cần kiểm tra loại đầu vào của bạn. Đây không phải là vấn đề nếu bạn đang sử dụng một hàm đặc biệt cho các đối số từ #invoke (tức là bạn có chức năng p.mainp._main, hoặc một cái gì đó tương tự).

Ví dụ 1 và 2 với kiểm tra loại

Ví dụ 1:

local args = getArgs(frame, {
	valueFunc = function (key, value)
		if key == 1 then
			return value
		elseif type(value) == 'string' then
			value = mw.text.trim(value)
			if value ~= '' then
				return value
			else
				return nil
			end
		else
			return value
		end
	end
})

Ví dụ 2:

local args = getArgs(frame, {
	valueFunc = function (key, value)
		if type(value) == 'string' then
			value = mw.ustring.lower(value)
			if mw.ustring.find(value, '%S') then
				return value
			else
				return nil
			end
		else
			return value
		end
	end
})

Ngoài ra, xin lưu ý rằng hàm valueFunc được gọi nhiều hơn hoặc ít hơn mỗi khi một đối số được yêu cầu từ bảng args, vì vậy nếu bạn quan tâm đến hiệu suất mà bạn nên chắc chắn rằng bạn không làm bất cứ điều gì không hiệu quả với mã của bạn.

Khung và khung cha[sửa mã nguồn]

Đối số trong bảng args có thể được truyền từ khung hiện tại hoặc từ khung chính của nó cùng một lúc. Để hiểu điều này có nghĩa là gì, dễ nhất là đưa ra một ví dụ. Hãy nói rằng chúng ta có một mô-đun gọi là Module:ExampleArgs. Mô-đun này in hai đối số vị trí đầu tiên mà nó được thông qua.

Mã nguồn của Mô đun:ExampleArgs
local getArgs = require('Module:Arguments').getArgs
local p = {}

function p.main(frame)
	local args = getArgs(frame)
	return p._main(args)
end

function p._main(args)
	local first = args[1] or ''
	local second = args[2] or ''
	return first .. ' ' .. second
end

return p

Module:ExampleArgs sau đó được gọi bởi Bản mẫu:ExampleArgs, có chứa đoạn mã {{#invoke:ExampleArgs|main|firstInvokeArg}}. Điều này tạo ra kết quả "firstInvokeArg".

Bây giờ nếu chúng ta gọi Bản mẫu:ExampleArgs, điều sau đây sẽ xảy ra:

Kết quả
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstInvokeArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstInvokeArg secondTemplateArg

Có ba tùy chọn bạn có thể đặt để thay đổi hành vi này: frameOnly, parentOnlyparentFirst. Nếu bạn đặt frameOnly sau đó chỉ các đối số được truyền từ khung hiện tại sẽ được chấp nhận; nếu bạn đặt parentOnly sau đó chỉ các đối số được truyền từ khung cha sẽ được chấp nhận; và nếu bạn đặt parentFirst sau đó các đối số sẽ được truyền từ cả khung hiện tại và khung chính, nhưng khung chính sẽ có mức độ ưu tiên so với khung hiện tại. Dưới đây là kết quả với Bản mẫu:ExampleArgs:

frameOnly
Kết quả
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstInvokeArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstInvokeArg
parentOnly
Kết quả
{{ExampleArgs}}
{{ExampleArgs|firstTemplateArg}} firstTemplateArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstTemplateArg secondTemplateArg
parentFirst
Kết quả
{{ExampleArgs}} firstInvokeArg
{{ExampleArgs|firstTemplateArg}} firstTemplateArg
{{ExampleArgs|firstTemplateArg|secondTemplateArg}} firstTemplateArg secondTemplateArg

Chú ý:

  1. Nếu bạn đặt cả hai tùy chọn frameOnlyparentOnly, mô-đun sẽ không tìm nạp bất kỳ đối số nào từ #invoke. Đây có lẽ không phải là những gì bạn muốn.
  2. Trong một số trường hợp, khung cha có thể không khả dụng, ví dụ: nếu getArgs thông qua khung cha chứ không phải khung hiện tại. Trong trường hợp này, chỉ các đối số khung sẽ được sử dụng (trừ khi parentOnly được đặt, trong trường hợp đó sẽ không có đối số nào được sử dụng) và tùy chọn parentFirstframeOnly sẽ không có tác dụng.

Wrappers[sửa mã nguồn]

Tùy chon wrappers được sử dụng để chỉ định một số lượng bản mẫu giới hạn như Bản mẫu wrapper, đó là, các bản mẫu có mục đích duy nhất là gọi một mô-đun. Nếu mô-đun phát hiện ra rằng nó đang được gọi từ một bản mẫu wrappers, nó sẽ chỉ kiểm tra các đối số trong khung cha; nếu không, nó sẽ chỉ kiểm tra các đối số trong khung được truyền cho getArgs. Điều này cho phép các mô-đun được gọi bằng #invoke hoặc thông qua mẫu wrappers mà không làm giảm hiệu suất liên quan đến việc phải kiểm tra cả khung và khung chính cho mỗi lần tra cứu đối số.

Ví dụ: nội dung duy nhất của Template:Side box (trừ nội dung trong cặp <noinclude>...</noinclude>) là {{#invoke:Side box|main}}. Không có điểm nào trong việc kiểm tra các đối số được truyền trực tiếp vào câu lệnh #invoke cho bản mẫu này, vì sẽ không có đối số nào được chỉ định ở đó. Chúng ta có thể tránh việc kiểm tra các đối số được truyền cho #invoke bằng cách sử dụng tùy chọn parentOnly, nhưng nếu chúng ta làm điều này thì #invoke cũng sẽ không hoạt động từ các trang khác. Nếu đây là trường hợp, |text=Some text trong mã {{#invoke:Side box|main|text=Some text}} sẽ bị bỏ qua hoàn toàn, bất kể nó được sử dụng từ trang nào. Bằng cách sử dụng tùy chọn wrappers để cụ thể hóa 'Bản mẫu:Side box' là một wrapper, ta có thể tạo {{#invoke:Side box|main|text=Some text}} hoạt động từ hầu hết các trang, trong khi vẫn không yêu cầu mô-đun kiểm tra các đối số trên chính trang Bản mẫu:Side box.

Wrappers có thể được chỉ định là một chuỗi hoặc là một chuỗi các chuỗi.

local args = getArgs(frame, {
	wrappers = 'Template:Wrapper template'
})


local args = getArgs(frame, {
	wrappers = {
		'Template:Wrapper 1',
		'Template:Wrapper 2',
		-- Bất kì số nào của bản mẫu wrapper cũng có thể thêm vào đây.
	}
})

Chú ý:

  1. Mô-đun sẽ tự động phát hiện nếu nó được gọi từ trang con /sandbox của bản mẫu wrapper, do đó không cần chỉ định rõ ràng các trang sandbox.
  2. Tùy chọn wrappers thay đổi hiệu quả mặc định của tùy chọn frameOnlyparentOnly. Nếu, ví dụ, parentOnly rõ ràng được đặt thành false với set wrappers, các cuộc gọi thông qua các bàn mẫu Wrapper sẽ dẫn đến cả hai đối số khung và đối số được tải, mặc dù các cuộc gọi không qua các mẫu trình bao bọc sẽ chỉ dẫn đến các đối số khung được tải.
  3. Nếu tùy chọn wrappers được đặt và không có khung cha nào khả dụng, mô-đun sẽ luôn nhận được các đối số từ khung được truyền cho getArgs.

Viết vào bảng args[sửa mã nguồn]

Đôi khi nó có thể hữu ích để viết các giá trị mới vào bảng args. Điều này là có thể với các thiết lập mặc định của mô-đun này. (Tuy nhiên, hãy nhớ rằng thường là phong cách mã hóa tốt hơn để tạo một bảng mới với các giá trị mới của bạn và sao chép các đối số từ bảng args khi cần.)

args.foo = 'some value'

Có thể thay đổi hành vi này với tùy chọn readOnlynoOverwrite. Nếu readOnly được đặt thì không thể ghi bất kỳ giá trị nào vào bảng args. Nếu noOverwrite được đặt, sau đó có thể thêm các giá trị mới vào bảng, nhưng không thể thêm giá trị nếu nó ghi đè lên bất kỳ đối số nào được truyền từ #invoke.

Cập tags Ref[sửa mã nguồn]

Mô đun này sử dụng metatables để tìm nạp các đối số từ #invoke. Điều này cho phép truy cập vào cả đối số khung và đối số khung cha mà không cần sử dụng hàm chức năng pairs(). Điều này có thể giúp có ích nếu mô-đun của bạn có thể được thông qua tags <ref>...</ref> làm đầu vào.

Ngay khi Tags <ref>...</ref> được truy cập từ Lua, chúng được xử lý bởi phần mềm MediaWiki và tài liệu tham khảo sẽ xuất hiện trong danh sách tham khảo ở cuối bài viết. Nếu mô-đun của bạn tiến hành bỏ qua thẻ tham chiếu từ đầu ra, bạn sẽ kết thúc bằng một tham chiếu ảo - một tham chiếu xuất hiện trong danh sách tham chiếu, nhưng không có số nào liên kết với nó. Đây là một vấn đề với các mô-đun sử dụng pairs() để phát hiện xem nên sử dụng các đối số từ khung hoặc khung cha, vì các mô-đun đó tự động xử lý mọi đối số có sẵn.

Mô-đun này giải quyết vấn đề này bằng cách cho phép truy cập vào cả đối số khung và khung cha, trong khi vẫn chỉ tìm nạp các đối số đó khi cần thiết. Vấn đề vẫn sẽ xảy ra nếu bạn sử dụng pairs(args) ở nơi khác trong mô-đun của bạn, tuy nhiên.

Những hạn chế đã biết[sửa mã nguồn]

Việc sử dụng các metatables cũng có nhược điểm của nó. Hầu hết các công cụ bảng Lua bình thường sẽ không hoạt động chính xác trên bảng args, bao gồm cả mã hoạt động #, hàm chức năng next(), và các chức năng trong thư viện bảng. Nếu việc sử dụng này là quan trọng cho mô-đun của bạn, bạn nên sử dụng chức năng xử lý đối số của riêng bạn thay vì mô-đun này.